{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "2ba3dda04decaffa",
   "metadata": {},
   "source": [
    "## Diffusion Model-扩散模型\n",
    "\n",
    "Denoising Diffusion Probabilistic Models（DDPM）论文：https://arxiv.org/abs/2006.11239\n",
    "Stable Diffusion论文：https://arxiv.org/abs/2112.10752\n",
    "\n",
    "DDPM是扩散模型的一种具体实现，Stable Diffusion基于DDPM的思想做了改进，OpenAI的DALL-E和谷歌的Imagen同样都是扩散模型。\n",
    "\n",
    "这里有很多图片：https://laion.ai/projects/\n",
    "对应的文搜图网站：https://github.com/rom1504/clip-retrieval"
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "扩散模型的核心思想就是通过不断对图像进行噪声添加和去噪，直到图像恢复到原始状态。",
   "id": "358e15c011ed1d04"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-25T07:08:31.050063Z",
     "start_time": "2025-08-25T07:08:29.329287Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from sympy import print_tree\n",
    "from torchvision import datasets, transforms\n",
    "\n",
    "dataset = datasets.MNIST(root='./data/', train=True, download=True, transform=transforms.ToTensor())\n",
    "img = dataset[0][0]\n",
    "\n",
    "plt.imshow(img.squeeze().cpu().numpy(), cmap='gray')"
   ],
   "id": "d43a8104677ad0df",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x118fc5f60>"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ],
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaAAAAGdCAYAAABU0qcqAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAGaxJREFUeJzt3X+QVWX9B/Bn/cGKCksrwrICCqhYIjgZEKmkiSCVI0iNms1gOToYOCqJDU6KVramaQ5Fyh8NZCn+mAlNpqEUZJkScECJcSzGZSgwAZPa5ZeAwvnOOczul1WQzrLLc/fe12vmmcu993z2Hs6ePe/7nPPc55YlSZIEADjCjjrSLwgAKQEEQBQCCIAoBBAAUQggAKIQQABEIYAAiEIAARDFMaHA7N27N7zzzjuhU6dOoaysLPbqAJBTOr/B1q1bQ3V1dTjqqKPaTwCl4dOrV6/YqwHAYVq/fn3o2bNn+zkFl/Z8AGj/DnU8b7MAmjFjRjjttNPCcccdF4YOHRpeffXV/6nOaTeA4nCo43mbBNDTTz8dJk+eHKZNmxZee+21MGjQoDBq1Kjw7rvvtsXLAdAeJW1gyJAhycSJE5vu79mzJ6murk5qamoOWdvQ0JDOzq1pmqaF9t3S4/knafUe0O7du8OKFSvCiBEjmh5LR0Gk95csWfKx5Xft2hW2bNnSrAFQ/Fo9gN57772wZ8+e0L1792aPp/c3btz4seVrampCRUVFUzMCDqA0RB8FN3Xq1NDQ0NDU0mF7ABS/Vv8cUNeuXcPRRx8dNm3a1Ozx9H5VVdXHli8vL88aAKWl1XtAHTp0COedd15YsGBBs9kN0vvDhg1r7ZcDoJ1qk5kQ0iHY48ePD5/73OfCkCFDwiOPPBK2b98evvWtb7XFywHQDrVJAF111VXh3//+d7j77ruzgQfnnntumD9//scGJgBQusrSsdihgKTDsNPRcAC0b+nAss6dOxfuKDgASpMAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCiOifOyUJiOPvro3DUVFRWhUE2aNKlFdccff3zumv79++eumThxYu6an/70p7lrrrnmmtASO3fuzF1z//3356659957QynSAwIgCgEEQHEE0D333BPKysqatbPOOqu1XwaAdq5NrgGdffbZ4aWXXvr/FznGpSYAmmuTZEgDp6qqqi1+NABFok2uAb311luhuro69O3bN1x77bVh3bp1B112165dYcuWLc0aAMWv1QNo6NChYfbs2WH+/Pnh0UcfDWvXrg0XXnhh2Lp16wGXr6mpyYaxNrZevXq19ioBUAoBNHr06PD1r389DBw4MIwaNSr84Q9/CPX19eGZZ5454PJTp04NDQ0NTW39+vWtvUoAFKA2Hx3QpUuXcOaZZ4a6uroDPl9eXp41AEpLm38OaNu2bWHNmjWhR48ebf1SAJRyAN1+++2htrY2/OMf/wivvPJKGDt2bDa9SUunwgCgOLX6Kbi33347C5vNmzeHk08+OVxwwQVh6dKl2b8BoM0C6KmnnmrtH0mB6t27d+6aDh065K75whe+kLsmfePT0muWeY0bN65Fr1Vs0jefeU2fPj13TXpWJa+DjcI9lL/+9a+5a9IzQPxvzAUHQBQCCIAoBBAAUQggAKIQQABEIYAAiEIAARCFAAIgCgEEQBQCCIAoBBAAUQggAKIoS5IkCQVky5Yt2Vdzc+Sce+65LapbuHBh7hq/2/Zh7969uWu+/e1vt+j7wo6EDRs2tKjuv//9b+6a1atXt+i1ilH6LdedO3c+6PN6QABEIYAAiEIAARCFAAIgCgEEQBQCCIAoBBAAUQggAKIQQABEIYAAiEIAARCFAAIgCgEEQBTHxHlZCsm6detaVLd58+bcNWbD3mfZsmW5a+rr63PXXHzxxaEldu/enbvmN7/5TYtei9KlBwRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAojAZKeE///lPi+qmTJmSu+arX/1q7prXX389d8306dPDkbJy5crcNZdeemnumu3bt+euOfvss0NL3HLLLS2qgzz0gACIQgABEIUAAiAKAQRAFAIIgCgEEABRCCAAohBAAEQhgACIQgABEIUAAiAKAQRAFGVJkiSh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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 1
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-25T07:08:40.491146Z",
     "start_time": "2025-08-25T07:08:40.486892Z"
    }
   },
   "cell_type": "code",
   "source": "img.shape",
   "id": "52561fc40dba0c91",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1, 28, 28])"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 2
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-25T07:09:23.327922Z",
     "start_time": "2025-08-25T07:09:23.269737Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch\n",
    "\n",
    "# 所谓噪声，本质上就是一堆随机数，通过randn_like生成一个和图片形状一致的随机矩阵，randn会生成一个正态分布矩阵\n",
    "noise = torch.randn_like(img)\n",
    "\n",
    "# 然后图片加上噪声\n",
    "img1 = img + noise\n",
    "\n",
    "plt.imshow(img1.squeeze().cpu().numpy(), cmap='gray')"
   ],
   "id": "320c99afa5f2a086",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x11c790eb0>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ],
      "image/png": "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9ttvFxsPPvigumb48OGq+YuKiso1H0dAAAAnCCAAQM0IoOeff16CgoLKTElJSRW9GABANVcp14Dat28vX3755f8vpHaVvdQEAHCkUpLBBE5cXFxl/NcAgBqiUq4B7dmzRxISErwRT+aRwL/2ONfCwkLvMc2XTgCAmq/CA6hnz57es8qXLl0qM2fOlKysLOnTp4+cOXPmsvOnpaVJgwYNSqdmzZpV9CoBAAIhgIYMGSK//e1vpVOnTjJo0CBZsmSJ5OTkyEcffXTZ+adNmya5ubml08GDByt6lQAAVVCljw6IjIyUG264Qfbu3XvZ74eGhnoTACCwVPp9QHl5eZKZmSnx8fGVvSgAQCAH0BNPPOG1//jhhx9k7dq1MmLECKlVq5b87ne/q+hFAQCqsQo/BXfo0CEvbE6ePCnR0dHSu3dvWb9+vfdvAAAqLYDmzJlTIf+PaRQaEhJS7vl79OihXoYZIGGjY8eO6pq+ffv6pZGkZptdS9NT22XZXO8zb2C0Ro4cKTaaNGmirtm0aZO6pk2bNuoaM6pUywwEspGamqquSU5OVtfY3C+4e/dudc33338vNh544AF1zWeffaauef311/3WRNimM03Dhg1V85vba8qDXnAAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMAJAggAUDMfSGeradOmEhYWVu75hw4dql7Gli1bxMbixYvVNebxFFoRERHqmtq19b/SKz0s8GoGDhyorlm5cqW6xjyqXatOnTpi+/wqrX379qlrOnfurK4xTxrWysjIEBvFxcV+2Y/q1avnl9+R7d+6zf66efNmdU2nTp3UNYMHDxZ/0f6e8vPzyzUfR0AAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMAJAggA4AQBBABwosp2w964caOqs/OFCxfUy0hMTBQbLVq0UNfUrVvXL12Wu3Xrpq6ZP3++2Lh48aK6Ji4uzi/dj3fs2KGusa2z6WTcsmVLdc0XX3yhrvn9738vNpYsWaKu+fTTT/3StXzSpEnqmqeeekps9OvXzy+vDz6fzy9/67bdumvVqlUp83MEBABwggACADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnCCAAABOVNlmpMOGDZPw8PByz79q1Sr1Mh577DGxsXbtWnXNd999p65p166duiY7O9svDUKN7du3q2tyc3PVNWFhYeqaw4cPi42oqCh1Te/evf3SALZ///7qmvfff19sbNiwwS/Levvtt9U1u3bt8kszYOP48ePqmmbNmqlrunTpoq5ZvHix2LD520hJSVHNn5+fX675OAICADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnCCAAABOEEAAACeqbDPS9PR0CQ4OLvf8qamp6mUsWLBAbNg0Fr377rvVNfv371fX9OzZU10TGxsrNvbt2+eXppBJSUl+aWBqZGZmqmu2bdvml6asNk1wQ0NDxUb37t3VNY0aNfLLPr53716/7Q8XLlxQ18TExKhr/vGPf6hrNK+Pl0pISFDXnDx5UjV/QUFBuebjCAgA4AQBBACoHgFknrtjntVjDuOCgoJ+cRrL5/PJs88+K/Hx8d7zfAYOHCh79uypyHUGAARiAJ09e1aSk5NlxowZl/3+yy+/LK+//rq89dZb3kOtIiIiZNCgQeU+JwgACAzqQQhDhgzxpssxRz/Tp0+Xp59+Wu68807va++99553kdscKY0aNera1xgAUCNU6DWgrKwsOXLkiHfarUSDBg28kVnr1q27bE1hYaGcPn26zAQAqPkqNIBM+FxuWK/5vOR7P5eWluaFVMlk8zx1AED143wU3LRp07x7IkqmgwcPul4lAEB1C6C4uDjv49GjR8t83Xxe8r3L3ShXv379MhMAoOar0ABq1aqVFzTLly8v/Zq5pmNGw6WkpFTkogAAgTYKLi8vr0wrDDPwwLQiMW04mjdvLpMnT5a//OUvcv3113uB9Mwzz3j3DA0fPryi1x0AEEgBtHnzZrn11ltLP58yZYr3cfTo0TJr1iyZOnWqd6/QuHHjJCcnR3r37i1Lly617sUEAKiZ1AHUr18/736fKzHdEV588UVvuhbm6EnTSDEjI0O9jPbt24uNzp07q2vOnTsn/nCl0Ya/xrxhsGHTWHTHjh3qmj59+vilUaphjuL98TM1bdpUXfPJJ5+oa0xXEhtz585V14SEhKhrzJtTreeff15dYy4D2DBvuLU6deqkromOjlbXmJv8bZizWFqNGzdWzV+7du3qMQoOABCYCCAAgBMEEADACQIIAOAEAQQAcIIAAgA4QQABAJwggAAAThBAAAAnCCAAgBMEEADACQIIAOAEAQQAqB7dsP3l1KlTqu66No972LJli/irC3RBQYG6JjMz0y/LsemOa7sdTDd1f2yH7du3i40BAwaoa/Lz89U15lElWj169FDXXPrsLo2hQ4eqa36tS/6VJCcnq2s2btzolw7VNl2gjcjISHXN0Z89Rbo8evXqJTaKi4vVNdnZ2ar5CwsLyzUfR0AAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMAJAggA4ESVbUbapk0bVYPR2bNnq5fx6KOPio2YmBh1zffff6+uadmyZaU3DTSSkpLExvz589U1586dU9dER0era1q3bi02cnNz1TU33nijuub8+fPqmp07d/plXzU2bdqkrmnXrp34g82227Vrl9Wy6tev75dt16VLF7/8rZe8tlZ2U9byNujlCAgA4AQBBABwggACADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnKiyzUhN886QkJByz9+rVy/1MjZu3Cg2iouL1TUdOnRQ1wQHB6trUlNT1TVFRUXir+1w4cIFv6zfoUOHxMYtt9yirjl+/Li6Ji8vT13z0EMPqWs2bNggNiIjI9U1HTt2VNdERESoa5YtW6auadCggdj473//q65p1aqVuub06dPqGp/PJzZWr16trklJSVHNTzNSAECVRgABAJwggAAAThBAAAAnCCAAgBMEEADACQIIAOAEAQQAcIIAAgA4QQABAJwggAAAThBAAAAnqmwz0mbNmklYWFi554+NjVUvo7CwUGzUq1dPXbN3716/NCPdtGmTuiYpKUlsPPjgg35pYLpy5Up1TXJysthYs2aNusamEa7Zv7WmT5+urunWrZvYKG8zyWutee+99/zSnPbmm28WG5rXoBJRUVHqml27dqlrWrRoITbatWunrlm+fLlq/vPnz5drPo6AAABOEEAAgOoRQKtWrZJhw4ZJQkKCBAUFyYIFC8p8f8yYMd7XL50GDx5ckesMAAjEADp79qx3fn3GjBlXnMcETnZ2duk0e/bsa11PAECgD0IYMmSIN/2a0NBQiYuLu5b1AgDUcJVyDciMWoqJiZG2bdvKhAkT5OTJk786Es08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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 3
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-25T07:14:44.085710Z",
     "start_time": "2025-08-25T07:14:44.077624Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch\n",
    "\n",
    "# 定义扩散参数\n",
    "T = 1000  # 总时间步\n",
    "betas = torch.linspace(0.0001, 0.02, T)# 线性增长的噪声方差\n",
    "alphas = 1 - betas\n",
    "alphas_bar = torch.cumprod(alphas, dim=0)\n",
    "print(alphas_bar)"
   ],
   "id": "71aa77a02cd7e03f",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([9.9990e-01, 9.9978e-01, 9.9964e-01, 9.9948e-01, 9.9930e-01, 9.9910e-01,\n",
      "        9.9888e-01, 9.9864e-01, 9.9838e-01, 9.9811e-01, 9.9781e-01, 9.9749e-01,\n",
      "        9.9715e-01, 9.9679e-01, 9.9641e-01, 9.9602e-01, 9.9560e-01, 9.9516e-01,\n",
      "        9.9471e-01, 9.9423e-01, 9.9374e-01, 9.9322e-01, 9.9269e-01, 9.9213e-01,\n",
      "        9.9156e-01, 9.9097e-01, 9.9035e-01, 9.8972e-01, 9.8907e-01, 9.8840e-01,\n",
      "        9.8771e-01, 9.8700e-01, 9.8627e-01, 9.8553e-01, 9.8476e-01, 9.8398e-01,\n",
      "        9.8317e-01, 9.8235e-01, 9.8151e-01, 9.8065e-01, 9.7977e-01, 9.7887e-01,\n",
      "        9.7795e-01, 9.7702e-01, 9.7606e-01, 9.7509e-01, 9.7410e-01, 9.7309e-01,\n",
      "        9.7206e-01, 9.7102e-01, 9.6995e-01, 9.6887e-01, 9.6777e-01, 9.6665e-01,\n",
      "        9.6551e-01, 9.6436e-01, 9.6319e-01, 9.6200e-01, 9.6079e-01, 9.5956e-01,\n",
      "        9.5832e-01, 9.5706e-01, 9.5578e-01, 9.5449e-01, 9.5318e-01, 9.5185e-01,\n",
      "        9.5050e-01, 9.4914e-01, 9.4776e-01, 9.4636e-01, 9.4494e-01, 9.4351e-01,\n",
      "        9.4207e-01, 9.4060e-01, 9.3912e-01, 9.3762e-01, 9.3611e-01, 9.3458e-01,\n",
      "        9.3304e-01, 9.3147e-01, 9.2990e-01, 9.2830e-01, 9.2669e-01, 9.2507e-01,\n",
      "        9.2343e-01, 9.2177e-01, 9.2010e-01, 9.1841e-01, 9.1671e-01, 9.1500e-01,\n",
      "        9.1326e-01, 9.1152e-01, 9.0976e-01, 9.0798e-01, 9.0619e-01, 9.0438e-01,\n",
      "        9.0256e-01, 9.0073e-01, 8.9888e-01, 8.9702e-01, 8.9514e-01, 8.9325e-01,\n",
      "        8.9135e-01, 8.8943e-01, 8.8750e-01, 8.8555e-01, 8.8359e-01, 8.8162e-01,\n",
      "        8.7964e-01, 8.7764e-01, 8.7563e-01, 8.7360e-01, 8.7157e-01, 8.6952e-01,\n",
      "        8.6746e-01, 8.6538e-01, 8.6330e-01, 8.6120e-01, 8.5909e-01, 8.5697e-01,\n",
      "        8.5483e-01, 8.5269e-01, 8.5053e-01, 8.4836e-01, 8.4618e-01, 8.4399e-01,\n",
      "        8.4179e-01, 8.3957e-01, 8.3735e-01, 8.3511e-01, 8.3287e-01, 8.3061e-01,\n",
      "        8.2834e-01, 8.2606e-01, 8.2378e-01, 8.2148e-01, 8.1917e-01, 8.1685e-01,\n",
      "        8.1453e-01, 8.1219e-01, 8.0984e-01, 8.0749e-01, 8.0512e-01, 8.0275e-01,\n",
      "        8.0037e-01, 7.9797e-01, 7.9557e-01, 7.9316e-01, 7.9075e-01, 7.8832e-01,\n",
      "        7.8589e-01, 7.8344e-01, 7.8099e-01, 7.7854e-01, 7.7607e-01, 7.7360e-01,\n",
      "        7.7111e-01, 7.6863e-01, 7.6613e-01, 7.6363e-01, 7.6112e-01, 7.5860e-01,\n",
      "        7.5608e-01, 7.5354e-01, 7.5101e-01, 7.4846e-01, 7.4591e-01, 7.4336e-01,\n",
      "        7.4080e-01, 7.3823e-01, 7.3565e-01, 7.3308e-01, 7.3049e-01, 7.2790e-01,\n",
      "        7.2530e-01, 7.2270e-01, 7.2010e-01, 7.1749e-01, 7.1487e-01, 7.1225e-01,\n",
      "        7.0963e-01, 7.0700e-01, 7.0436e-01, 7.0172e-01, 6.9908e-01, 6.9644e-01,\n",
      "        6.9379e-01, 6.9113e-01, 6.8847e-01, 6.8581e-01, 6.8315e-01, 6.8048e-01,\n",
      "        6.7781e-01, 6.7514e-01, 6.7246e-01, 6.6978e-01, 6.6710e-01, 6.6441e-01,\n",
      "        6.6173e-01, 6.5904e-01, 6.5635e-01, 6.5365e-01, 6.5096e-01, 6.4826e-01,\n",
      "        6.4556e-01, 6.4286e-01, 6.4016e-01, 6.3745e-01, 6.3475e-01, 6.3204e-01,\n",
      "        6.2934e-01, 6.2663e-01, 6.2392e-01, 6.2121e-01, 6.1850e-01, 6.1579e-01,\n",
      "        6.1308e-01, 6.1037e-01, 6.0765e-01, 6.0494e-01, 6.0223e-01, 5.9952e-01,\n",
      "        5.9681e-01, 5.9410e-01, 5.9139e-01, 5.8868e-01, 5.8597e-01, 5.8326e-01,\n",
      "        5.8055e-01, 5.7785e-01, 5.7514e-01, 5.7244e-01, 5.6974e-01, 5.6703e-01,\n",
      "        5.6433e-01, 5.6164e-01, 5.5894e-01, 5.5624e-01, 5.5355e-01, 5.5086e-01,\n",
      "        5.4817e-01, 5.4549e-01, 5.4280e-01, 5.4012e-01, 5.3744e-01, 5.3476e-01,\n",
      "        5.3209e-01, 5.2942e-01, 5.2675e-01, 5.2409e-01, 5.2142e-01, 5.1876e-01,\n",
      "        5.1611e-01, 5.1346e-01, 5.1081e-01, 5.0816e-01, 5.0552e-01, 5.0288e-01,\n",
      "        5.0024e-01, 4.9761e-01, 4.9499e-01, 4.9236e-01, 4.8974e-01, 4.8713e-01,\n",
      "        4.8452e-01, 4.8191e-01, 4.7931e-01, 4.7671e-01, 4.7412e-01, 4.7153e-01,\n",
      "        4.6895e-01, 4.6637e-01, 4.6380e-01, 4.6123e-01, 4.5867e-01, 4.5611e-01,\n",
      "        4.5356e-01, 4.5101e-01, 4.4846e-01, 4.4593e-01, 4.4340e-01, 4.4087e-01,\n",
      "        4.3835e-01, 4.3583e-01, 4.3332e-01, 4.3082e-01, 4.2832e-01, 4.2583e-01,\n",
      "        4.2335e-01, 4.2087e-01, 4.1839e-01, 4.1593e-01, 4.1347e-01, 4.1101e-01,\n",
      "        4.0856e-01, 4.0612e-01, 4.0369e-01, 4.0126e-01, 3.9884e-01, 3.9642e-01,\n",
      "        3.9401e-01, 3.9161e-01, 3.8921e-01, 3.8683e-01, 3.8444e-01, 3.8207e-01,\n",
      "        3.7970e-01, 3.7734e-01, 3.7499e-01, 3.7265e-01, 3.7031e-01, 3.6798e-01,\n",
      "        3.6565e-01, 3.6334e-01, 3.6103e-01, 3.5872e-01, 3.5643e-01, 3.5414e-01,\n",
      "        3.5187e-01, 3.4959e-01, 3.4733e-01, 3.4508e-01, 3.4283e-01, 3.4059e-01,\n",
      "        3.3836e-01, 3.3613e-01, 3.3391e-01, 3.3171e-01, 3.2951e-01, 3.2731e-01,\n",
      "        3.2513e-01, 3.2295e-01, 3.2078e-01, 3.1862e-01, 3.1647e-01, 3.1433e-01,\n",
      "        3.1219e-01, 3.1007e-01, 3.0795e-01, 3.0584e-01, 3.0374e-01, 3.0164e-01,\n",
      "        2.9956e-01, 2.9748e-01, 2.9541e-01, 2.9335e-01, 2.9130e-01, 2.8926e-01,\n",
      "        2.8722e-01, 2.8520e-01, 2.8318e-01, 2.8117e-01, 2.7917e-01, 2.7718e-01,\n",
      "        2.7520e-01, 2.7323e-01, 2.7126e-01, 2.6931e-01, 2.6736e-01, 2.6542e-01,\n",
      "        2.6349e-01, 2.6157e-01, 2.5966e-01, 2.5775e-01, 2.5586e-01, 2.5397e-01,\n",
      "        2.5210e-01, 2.5023e-01, 2.4837e-01, 2.4652e-01, 2.4468e-01, 2.4284e-01,\n",
      "        2.4102e-01, 2.3920e-01, 2.3740e-01, 2.3560e-01, 2.3381e-01, 2.3203e-01,\n",
      "        2.3026e-01, 2.2850e-01, 2.2675e-01, 2.2501e-01, 2.2327e-01, 2.2155e-01,\n",
      "        2.1983e-01, 2.1812e-01, 2.1642e-01, 2.1473e-01, 2.1305e-01, 2.1138e-01,\n",
      "        2.0972e-01, 2.0806e-01, 2.0642e-01, 2.0478e-01, 2.0315e-01, 2.0153e-01,\n",
      "        1.9992e-01, 1.9832e-01, 1.9673e-01, 1.9515e-01, 1.9357e-01, 1.9201e-01,\n",
      "        1.9045e-01, 1.8890e-01, 1.8736e-01, 1.8583e-01, 1.8431e-01, 1.8280e-01,\n",
      "        1.8129e-01, 1.7980e-01, 1.7831e-01, 1.7683e-01, 1.7537e-01, 1.7391e-01,\n",
      "        1.7245e-01, 1.7101e-01, 1.6958e-01, 1.6815e-01, 1.6673e-01, 1.6533e-01,\n",
      "        1.6393e-01, 1.6254e-01, 1.6115e-01, 1.5978e-01, 1.5841e-01, 1.5706e-01,\n",
      "        1.5571e-01, 1.5437e-01, 1.5304e-01, 1.5171e-01, 1.5040e-01, 1.4909e-01,\n",
      "        1.4779e-01, 1.4650e-01, 1.4522e-01, 1.4395e-01, 1.4269e-01, 1.4143e-01,\n",
      "        1.4018e-01, 1.3894e-01, 1.3771e-01, 1.3649e-01, 1.3527e-01, 1.3406e-01,\n",
      "        1.3286e-01, 1.3167e-01, 1.3049e-01, 1.2932e-01, 1.2815e-01, 1.2699e-01,\n",
      "        1.2584e-01, 1.2470e-01, 1.2356e-01, 1.2243e-01, 1.2131e-01, 1.2020e-01,\n",
      "        1.1910e-01, 1.1800e-01, 1.1691e-01, 1.1583e-01, 1.1476e-01, 1.1369e-01,\n",
      "        1.1264e-01, 1.1159e-01, 1.1054e-01, 1.0951e-01, 1.0848e-01, 1.0746e-01,\n",
      "        1.0645e-01, 1.0544e-01, 1.0445e-01, 1.0346e-01, 1.0247e-01, 1.0150e-01,\n",
      "        1.0053e-01, 9.9567e-02, 9.8613e-02, 9.7667e-02, 9.6727e-02, 9.5794e-02,\n",
      "        9.4869e-02, 9.3950e-02, 9.3039e-02, 9.2134e-02, 9.1237e-02, 9.0346e-02,\n",
      "        8.9463e-02, 8.8586e-02, 8.7716e-02, 8.6853e-02, 8.5996e-02, 8.5146e-02,\n",
      "        8.4303e-02, 8.3467e-02, 8.2637e-02, 8.1814e-02, 8.0998e-02, 8.0188e-02,\n",
      "        7.9384e-02, 7.8587e-02, 7.7797e-02, 7.7012e-02, 7.6235e-02, 7.5463e-02,\n",
      "        7.4698e-02, 7.3939e-02, 7.3186e-02, 7.2440e-02, 7.1700e-02, 7.0966e-02,\n",
      "        7.0238e-02, 6.9516e-02, 6.8800e-02, 6.8090e-02, 6.7386e-02, 6.6688e-02,\n",
      "        6.5996e-02, 6.5309e-02, 6.4629e-02, 6.3954e-02, 6.3285e-02, 6.2622e-02,\n",
      "        6.1965e-02, 6.1313e-02, 6.0667e-02, 6.0026e-02, 5.9391e-02, 5.8762e-02,\n",
      "        5.8138e-02, 5.7520e-02, 5.6907e-02, 5.6299e-02, 5.5697e-02, 5.5100e-02,\n",
      "        5.4508e-02, 5.3922e-02, 5.3341e-02, 5.2765e-02, 5.2194e-02, 5.1628e-02,\n",
      "        5.1068e-02, 5.0513e-02, 4.9962e-02, 4.9417e-02, 4.8876e-02, 4.8341e-02,\n",
      "        4.7810e-02, 4.7284e-02, 4.6764e-02, 4.6247e-02, 4.5736e-02, 4.5230e-02,\n",
      "        4.4728e-02, 4.4231e-02, 4.3738e-02, 4.3250e-02, 4.2767e-02, 4.2288e-02,\n",
      "        4.1814e-02, 4.1344e-02, 4.0879e-02, 4.0418e-02, 3.9961e-02, 3.9509e-02,\n",
      "        3.9061e-02, 3.8618e-02, 3.8178e-02, 3.7743e-02, 3.7312e-02, 3.6886e-02,\n",
      "        3.6463e-02, 3.6045e-02, 3.5631e-02, 3.5220e-02, 3.4814e-02, 3.4412e-02,\n",
      "        3.4014e-02, 3.3619e-02, 3.3229e-02, 3.2842e-02, 3.2460e-02, 3.2081e-02,\n",
      "        3.1705e-02, 3.1334e-02, 3.0966e-02, 3.0603e-02, 3.0242e-02, 2.9886e-02,\n",
      "        2.9533e-02, 2.9183e-02, 2.8837e-02, 2.8495e-02, 2.8156e-02, 2.7821e-02,\n",
      "        2.7489e-02, 2.7160e-02, 2.6835e-02, 2.6513e-02, 2.6195e-02, 2.5879e-02,\n",
      "        2.5567e-02, 2.5259e-02, 2.4953e-02, 2.4651e-02, 2.4352e-02, 2.4056e-02,\n",
      "        2.3763e-02, 2.3474e-02, 2.3187e-02, 2.2903e-02, 2.2623e-02, 2.2345e-02,\n",
      "        2.2071e-02, 2.1799e-02, 2.1530e-02, 2.1264e-02, 2.1001e-02, 2.0741e-02,\n",
      "        2.0484e-02, 2.0229e-02, 1.9977e-02, 1.9728e-02, 1.9482e-02, 1.9238e-02,\n",
      "        1.8997e-02, 1.8758e-02, 1.8523e-02, 1.8289e-02, 1.8059e-02, 1.7831e-02,\n",
      "        1.7605e-02, 1.7382e-02, 1.7161e-02, 1.6943e-02, 1.6728e-02, 1.6514e-02,\n",
      "        1.6304e-02, 1.6095e-02, 1.5889e-02, 1.5685e-02, 1.5484e-02, 1.5284e-02,\n",
      "        1.5087e-02, 1.4893e-02, 1.4700e-02, 1.4510e-02, 1.4321e-02, 1.4135e-02,\n",
      "        1.3952e-02, 1.3770e-02, 1.3590e-02, 1.3413e-02, 1.3237e-02, 1.3064e-02,\n",
      "        1.2892e-02, 1.2723e-02, 1.2555e-02, 1.2389e-02, 1.2226e-02, 1.2064e-02,\n",
      "        1.1904e-02, 1.1746e-02, 1.1590e-02, 1.1436e-02, 1.1284e-02, 1.1133e-02,\n",
      "        1.0984e-02, 1.0837e-02, 1.0692e-02, 1.0548e-02, 1.0407e-02, 1.0266e-02,\n",
      "        1.0128e-02, 9.9911e-03, 9.8560e-03, 9.7225e-03, 9.5906e-03, 9.4603e-03,\n",
      "        9.3316e-03, 9.2044e-03, 9.0788e-03, 8.9548e-03, 8.8322e-03, 8.7112e-03,\n",
      "        8.5916e-03, 8.4735e-03, 8.3569e-03, 8.2417e-03, 8.1279e-03, 8.0155e-03,\n",
      "        7.9046e-03, 7.7950e-03, 7.6867e-03, 7.5799e-03, 7.4743e-03, 7.3701e-03,\n",
      "        7.2672e-03, 7.1655e-03, 7.0652e-03, 6.9661e-03, 6.8683e-03, 6.7717e-03,\n",
      "        6.6763e-03, 6.5822e-03, 6.4892e-03, 6.3974e-03, 6.3068e-03, 6.2173e-03,\n",
      "        6.1290e-03, 6.0419e-03, 5.9558e-03, 5.8709e-03, 5.7870e-03, 5.7042e-03,\n",
      "        5.6225e-03, 5.5419e-03, 5.4623e-03, 5.3837e-03, 5.3062e-03, 5.2297e-03,\n",
      "        5.1541e-03, 5.0796e-03, 5.0060e-03, 4.9334e-03, 4.8618e-03, 4.7911e-03,\n",
      "        4.7213e-03, 4.6525e-03, 4.5845e-03, 4.5175e-03, 4.4514e-03, 4.3861e-03,\n",
      "        4.3217e-03, 4.2582e-03, 4.1955e-03, 4.1336e-03, 4.0726e-03, 4.0124e-03,\n",
      "        3.9530e-03, 3.8945e-03, 3.8367e-03, 3.7796e-03, 3.7234e-03, 3.6679e-03,\n",
      "        3.6132e-03, 3.5592e-03, 3.5060e-03, 3.4534e-03, 3.4016e-03, 3.3506e-03,\n",
      "        3.3002e-03, 3.2505e-03, 3.2014e-03, 3.1531e-03, 3.1054e-03, 3.0584e-03,\n",
      "        3.0120e-03, 2.9663e-03, 2.9212e-03, 2.8768e-03, 2.8329e-03, 2.7897e-03,\n",
      "        2.7471e-03, 2.7051e-03, 2.6636e-03, 2.6228e-03, 2.5825e-03, 2.5428e-03,\n",
      "        2.5036e-03, 2.4650e-03, 2.4270e-03, 2.3894e-03, 2.3525e-03, 2.3160e-03,\n",
      "        2.2801e-03, 2.2446e-03, 2.2097e-03, 2.1753e-03, 2.1414e-03, 2.1079e-03,\n",
      "        2.0750e-03, 2.0425e-03, 2.0104e-03, 1.9789e-03, 1.9478e-03, 1.9171e-03,\n",
      "        1.8869e-03, 1.8572e-03, 1.8278e-03, 1.7989e-03, 1.7704e-03, 1.7423e-03,\n",
      "        1.7147e-03, 1.6874e-03, 1.6606e-03, 1.6341e-03, 1.6080e-03, 1.5823e-03,\n",
      "        1.5570e-03, 1.5321e-03, 1.5075e-03, 1.4833e-03, 1.4595e-03, 1.4360e-03,\n",
      "        1.4128e-03, 1.3900e-03, 1.3676e-03, 1.3455e-03, 1.3237e-03, 1.3022e-03,\n",
      "        1.2811e-03, 1.2602e-03, 1.2397e-03, 1.2195e-03, 1.1996e-03, 1.1800e-03,\n",
      "        1.1607e-03, 1.1417e-03, 1.1230e-03, 1.1046e-03, 1.0864e-03, 1.0686e-03,\n",
      "        1.0509e-03, 1.0336e-03, 1.0165e-03, 9.9974e-04, 9.8319e-04, 9.6689e-04,\n",
      "        9.5085e-04, 9.3505e-04, 9.1950e-04, 9.0419e-04, 8.8911e-04, 8.7427e-04,\n",
      "        8.5966e-04, 8.4527e-04, 8.3111e-04, 8.1717e-04, 8.0345e-04, 7.8994e-04,\n",
      "        7.7664e-04, 7.6355e-04, 7.5067e-04, 7.3799e-04, 7.2551e-04, 7.1322e-04,\n",
      "        7.0113e-04, 6.8923e-04, 6.7752e-04, 6.6600e-04, 6.5465e-04, 6.4349e-04,\n",
      "        6.3250e-04, 6.2169e-04, 6.1106e-04, 6.0059e-04, 5.9029e-04, 5.8015e-04,\n",
      "        5.7018e-04, 5.6036e-04, 5.5071e-04, 5.4121e-04, 5.3186e-04, 5.2266e-04,\n",
      "        5.1362e-04, 5.0472e-04, 4.9596e-04, 4.8734e-04, 4.7887e-04, 4.7053e-04,\n",
      "        4.6233e-04, 4.5426e-04, 4.4633e-04, 4.3852e-04, 4.3084e-04, 4.2329e-04,\n",
      "        4.1586e-04, 4.0855e-04, 4.0137e-04, 3.9430e-04, 3.8735e-04, 3.8051e-04,\n",
      "        3.7379e-04, 3.6718e-04, 3.6067e-04, 3.5428e-04, 3.4799e-04, 3.4181e-04,\n",
      "        3.3573e-04, 3.2975e-04, 3.2387e-04, 3.1809e-04, 3.1240e-04, 3.0682e-04,\n",
      "        3.0132e-04, 2.9592e-04, 2.9061e-04, 2.8539e-04, 2.8025e-04, 2.7521e-04,\n",
      "        2.7024e-04, 2.6537e-04, 2.6057e-04, 2.5586e-04, 2.5123e-04, 2.4667e-04,\n",
      "        2.4220e-04, 2.3780e-04, 2.3347e-04, 2.2922e-04, 2.2504e-04, 2.2094e-04,\n",
      "        2.1690e-04, 2.1293e-04, 2.0904e-04, 2.0520e-04, 2.0144e-04, 1.9774e-04,\n",
      "        1.9410e-04, 1.9053e-04, 1.8702e-04, 1.8357e-04, 1.8018e-04, 1.7685e-04,\n",
      "        1.7358e-04, 1.7036e-04, 1.6720e-04, 1.6410e-04, 1.6105e-04, 1.5805e-04,\n",
      "        1.5511e-04, 1.5222e-04, 1.4937e-04, 1.4658e-04, 1.4384e-04, 1.4115e-04,\n",
      "        1.3850e-04, 1.3590e-04, 1.3335e-04, 1.3084e-04, 1.2838e-04, 1.2596e-04,\n",
      "        1.2358e-04, 1.2125e-04, 1.1896e-04, 1.1671e-04, 1.1450e-04, 1.1232e-04,\n",
      "        1.1019e-04, 1.0810e-04, 1.0604e-04, 1.0402e-04, 1.0204e-04, 1.0009e-04,\n",
      "        9.8180e-05, 9.6302e-05, 9.4459e-05, 9.2649e-05, 9.0871e-05, 8.9126e-05,\n",
      "        8.7413e-05, 8.5731e-05, 8.4080e-05, 8.2458e-05, 8.0867e-05, 7.9304e-05,\n",
      "        7.7770e-05, 7.6264e-05, 7.4786e-05, 7.3335e-05, 7.1911e-05, 7.0513e-05,\n",
      "        6.9140e-05, 6.7793e-05, 6.6471e-05, 6.5173e-05, 6.3900e-05, 6.2650e-05,\n",
      "        6.1423e-05, 6.0219e-05, 5.9038e-05, 5.7878e-05, 5.6740e-05, 5.5623e-05,\n",
      "        5.4527e-05, 5.3452e-05, 5.2397e-05, 5.1361e-05, 5.0345e-05, 4.9349e-05,\n",
      "        4.8370e-05, 4.7411e-05, 4.6469e-05, 4.5545e-05, 4.4639e-05, 4.3750e-05,\n",
      "        4.2877e-05, 4.2022e-05, 4.1182e-05, 4.0358e-05])\n"
     ]
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-25T07:14:10.226628Z",
     "start_time": "2025-08-25T07:14:10.222867Z"
    }
   },
   "cell_type": "code",
   "source": [
    "alphas = torch.tensor([2, 3, 1, 4])\n",
    "cumulative_product = torch.cumprod(alphas, dim=0)\n",
    "print(cumulative_product)"
   ],
   "id": "75902cce6c30bba2",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([ 2,  6,  6, 24])\n"
     ]
    }
   ],
   "execution_count": 6
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-25T07:16:06.362760Z",
     "start_time": "2025-08-25T07:16:06.305815Z"
    }
   },
   "cell_type": "code",
   "source": [
    "t = 10\n",
    "noise = torch.randn_like(img)\n",
    "sqrt_alpha_bar_t = torch.sqrt(alphas_bar[t])  # [B]\n",
    "sqrt_one_minus_alpha_bar_t = torch.sqrt(1 - alphas_bar[t])\n",
    "img2 = sqrt_alpha_bar_t * img + sqrt_one_minus_alpha_bar_t * noise\n",
    "plt.imshow(img2.squeeze().cpu().numpy(), cmap='gray')"
   ],
   "id": "4943d0bfee0d2465",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x11cbc7040>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ],
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaAAAAGdCAYAAABU0qcqAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAIu5JREFUeJzt3X1sVvX9//F3ofc39P6WtgioICpsKiJTGQoBWUJEiZFBMjAGIgMjMKfpoqK7q9PEMQ3DPzbtzPCORDSYDaMoMB24gWPETAmFKnctN4Xe39H2/PI5/tpvq9z086Y9n6vX9XwkV8rVXm/Ouc51zvW6zjmf632iPM/zBACAgA0JeoIAABgEEADACQIIAOAEAQQAcIIAAgA4QQABAJwggAAAThBAAAAnoiXEdHZ2yrFjxyQlJUWioqJczw4AwJLpb1BfXy8FBQUyZMiQwRNAJnyKiopczwYA4BIdPnxYCgsLB08AmT0fY+jQoVZ7QLm5udbTulAyX0h0tP1ia29vD2Q6zc3N1jVNTU2ikZaWZl1z9uzZQKbT2toqGprXqbq62rpGs3efkZFhXRMXFycaLS0tgUyrra0tkNc2KSlJNMz7UKhug63KdTwnJ2fA11dzJOurr77qfj8PPIDWrl0rzz77rFRVVcmECRPkhRdekBtvvLHPT9T8tHnSmjDRBlBQ0wqqRnuoM6j507wJBPnaapafpiaoZRfktEJ5uwj15xQV4HarndbF6gZkEMIbb7whq1atktWrV8tnn33mB9DMmTPlxIkTAzE5AMAgNCAB9Nxzz8nixYvlvvvuk3HjxsmLL74oiYmJ8tJLLw3E5AAAg1C/B5A5prt7926ZPn36/01kyBD//o4dO855HLOurq7XDQAQ/vo9gE6dOiUdHR3fGRRg7pvzQd9WWloqqamp3TdGwAFAZHD+RdSSkhKpra3tvplhewCA8Nfvo+CysrL8kSPHjx/v9XtzPy8v75xDN7VDRQEAg1e/7wHFxsbK9ddfL1u2bOk1Jtzcnzx5cn9PDgAwSA3I94DMEOyFCxfKDTfc4H/3Z82aNdLY2OiPigMAYMAC6N5775WTJ0/KE0884Q88+N73viebN29WdSsAAISnKM90jQshZhi2GQ1n2o7YfGPXnHsKqgWNOaQYxLePNdPRvJzZ2dmi8fXXX1vXmBGSti7WzqO/WuoYmvORmmWuaQ1jmjvaMgN7NMz39oLqNhBEiyptKx7NtA4dOhRIm6VmRcsfbfsj23ZY5r3LLAez/g0bNix0R8EBACITAQQAcIIAAgA4QQABAJwggAAAThBAAAAnCCAAgBMEEADACQIIAOAEAQQAcIIAAgA4QQABAMKnG3Z/yMzM9C9sN5DOnDmjqtPMV3JyciDNUuPj41WXUQ+qYWVUVFQgzRMv1ACxv5uYapa5prGoppGraeyroWksWllZaV1TWFgYyPanWXZGS0uLdU1MTIx1TWtrq3WNto+0prmv7XtRXxspswcEAHCCAAIAOEEAAQCcIIAAAE4QQAAAJwggAIATBBAAwAkCCADgBAEEAHCCAAIAOEEAAQCcIIAAAE4QQAAAJ0K2G3ZdXZ1VR964uDjracTGxlrXaOs0HXw1XZbPnj0bSI2247SmU3B0tP1qqu2kfuLEiUA6Tjc2NoZ0F2jNcyouLrauqampsa7Jzs62rqmurhYNTcdpTcf3eMW2rukSb9Op+lK2dTONvnTZZw8IAOAEAQQAcIIAAgA4QQABAJwggAAAThBAAAAnCCAAgBMEEADACQIIAOAEAQQAcIIAAgA4QQABAJwI2WakprmoTTNSDU2TSyMpKSmQJpfp6enWNZplpl0OQTVqTExMtK7pSyPEcyksLLSuKS8vt64ZP368dU1VVVVgTVk1NOuepqGttnmuRkJCgnVNcnKydU1LS4t1TWtrq2hotnfb+etrw1P2gAAAThBAAAAnCCAAgBMEEADACQIIAOAEAQQAcIIAAgA4QQABAJwggAAAThBAAAAnCCAAgBMEEADAiZBtRpqSkmLVSLG6utp6GvHx8RIUTYPCoBqlxsTEqKalaY5ZV1cXyLILsglnfn6+dc3Jkyeta4qLi61rZs2aJRqZmZnWNcOHD7eu+e1vf2tds3LlSuuaKVOmiEZjY6N1zUsvvWRds379+kBeo6AaI3d0dPTpcewBAQCcIIAAAOERQE8++aR/zZeet7Fjx/b3ZAAAg9yAnAO6+uqr5YMPPrjkC54BAMLXgCSDCZy8vLyB+K8BAGFiQM4B7d+/XwoKCmTUqFGyYMECOXTo0AUvK2tGRvW8AQDCX78H0KRJk6SsrEw2b94s69atk4qKCrn11lulvr7+nI8vLS2V1NTU7ltRUVF/zxIAIBICyHzv4J577pHx48fLzJkz5W9/+5vU1NTIm2++ec7Hl5SUSG1tbfft8OHD/T1LAIAQNOCjA9LS0uTKK6+U8vLyc/49Li7OvwEAIsuAfw+ooaFBDhw4oPq2OAAgfPV7AD388MOybds2+eqrr+Sf//yn3HXXXX5blB//+Mf9PSkAwCDW74fgjhw54oeN6c2WnZ0tt9xyi+zcudP/NwAAAxZAr7/+er/8P6dOnZIhQ/q+gxYbG2s9De0XZI8ePWpdk5GRYV2jGZLe1tZmXZObmysaZqh9EMvcjKK0NW7cONEoLCy0rrnuuuusa8zXD2xpvltXWVkpGp7nqQ6321q2bJl1zezZs61rmpqaROPLL7+0rjnf+e4LaWlpsa5pbm4W7Xl5W+3t7VaP7+zs7NPj6AUHAHCCAAIAOEEAAQCcIIAAAE4QQAAAJwggAIATBBAAwAkCCADgBAEEAHCCAAIAOEEAAQCcIIAAAOF5QTqtpKQkq2akmsadpmO3hqYppEZKSop1TWJionWNuRS6xpo1a6xr0tPTA2nUqO2+rmnmaq7kG8T8ne+y9v29vLWNLp9++mnrGnO1ZFvvvfeedU1jY6Nou/sPdONOw1yyxpb2Qp6nT5+2romPj7d6PM1IAQAhjQACADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnCCAAABOEEAAACdCtht2X7upXkoX6Oho3dNPSEiQIGi66mo63Wo6QGtpuv5qXtuoqCgJYr0zxowZY13z73//O5DO0ZMmTRKN1tZW65r169db16SlpQXSqTs2Nla0XfmDmL84RWfrhoYGCWobtH2vpBs2ACCkEUAAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMCJkG1GWl1dbdVQctiwYYE0DdQ2NmxsbAykCWdLS4t1TXp6umiUlZVZ1/zgBz+wrtmxY4d1zUMPPSQamqaQ//jHP6xrVqxYEcg6lJWVJRrz588PpJHr2bNnrWtSUlKsa2pra0Wjo6MjkOc0VNEgNDk5WYJi+9rSjBQAENIIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMAJAggA4ETINiM1jTiHDOl7PtbV1VlPY9SoUaJRWVlpXaOZP02D1YSEBOuapqYm0di4cWMgNZrnNG7cONG46667rGv+9Kc/Wde0tbUF0hizvr5eNFauXGldc9lll1nX2Gzjl9JwNz4+XoKiaSyamppqXXPw4EHRyMnJsa5pb2+3ejzNSAEAIY0AAgAMjgDavn27zJ49WwoKCvzr9bz99tu9/u55njzxxBOSn5/vHzqZPn267N+/vz/nGQAQiQFkLoo1YcIEWbt27Tn//swzz8jzzz8vL774onz66aeSlJQkM2fOVB23BQCEL+tBCLNmzfJv52L2ftasWSOPPfaY3Hnnnf7vXnnlFcnNzfX3lObNm3fpcwwACAv9eg6ooqJCqqqq/MNuPUd3TJo06byXVW5tbfVHiPW8AQDCX78GkAkfw+zx9GTud/3t20pLS/2Q6roVFRX15ywBAEKU81FwJSUlUltb2307fPiw61kCAAy2AMrLy/N/Hj9+vNfvzf2uv31bXFyc/4XLnjcAQPjr1wAaOXKkHzRbtmzp/p05p2NGw02ePLk/JwUAiLRRcA0NDVJeXt5r4MGePXskIyNDiouLZcWKFfLrX/9arrjiCj+QHn/8cf87Q3PmzOnveQcARFIA7dq1S2677bbu+6tWrfJ/Lly4UMrKyuSRRx7xvyu0ZMkSqampkVtuuUU2b94caC8mAEDoi/LMl3dCiDlkZ0bDpaWl+Z0W+kpz7ig5OVk0Tpw4YV1jvpBrq7m5OZCGlZqGkIbN62PbpPBSGiEav/nNb0Rj6tSp1jWaTh+PPvqodU2QX+aOjY21rtF8hULzwVTzlqVpEKp9TpmZmdY1ra2tgWwX2ve9841ivtBr1DWw7ELvzc5HwQEAIhMBBABwggACADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnCCAAACD43IMQTFXSrXp0qzp8KrpQNt1TaQgOteaZWArOjo6kOlou2FruhKby3vYWrt2rWhkZWVZ1/S8PElfmetl2dq+fbt1TUJCgmiYS6kENS1bpsNyUJ3vNXUHDx60rikoKLCuMVcMCOr9KyYmZkC63rMHBABwggACADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnCCAAABORHme50kIqaurk9TUVMnPz7dqRqp5GtpmpJoGhZpmpGY52Kqvr7euaWtrE42UlJRA5i82Njaw5zRu3Djrmj/84Q8ShK1bt1rXfPHFF6ppvffee9Y1TU1Ngby2mm29ublZNDTbYFVVlXVNUVGRdU11dbVoJCUlWdccOXLE+jXq6OjwG8cOGzbsvI9jDwgA4AQBBABwggACADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnIiWEGWad9o0I42Li7OexrFjxySoZn6aBqaaZoONjY2BNWpMSEiwrgmq962miaSxf/9+65rnn3/eumblypXWNbfddpt1zX333ScamvV106ZNgTTu1Gx/mnXViImJsa6Jj48PpElvenq6aGiaMF+ooej5tvMzZ85c9HHsAQEAnCCAAABOEEAAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnCCAAABOEEAAACcIIACAE1FeUN0h+6iurs5vJJmXl2fVjNTmsV1aWlpEIy0tTdVc1VZlZeWANw00MjMzRUPznDRNYzUNVs+ePSsaQ4cODWQ9uummm6xrVqxYYV1z1VVXiYZme9q8ebN1zdq1a61rjh49GkhTUe16pGn22dHREci2ZBw/fty65uqrr7Z+Pl988YXU1tZe8D2JPSAAgBMEEABgcATQ9u3bZfbs2VJQUCBRUVHy9ttv9/r7okWL/N/3vN1xxx39Oc8AgEgMIHM8fsKECRc8dmsCx5y/6Lq99tprlzqfAIBIvyLqrFmz/NvFTo6ZQQQAAAR6Dmjr1q2Sk5MjY8aMkaVLl17w0tJmxIgZ+dbzBgAIf/0eQObw2yuvvCJbtmyR3/3ud7Jt2zZ/j+l8wwxLS0v9Ydddt6Kiov6eJQBAOByCu5h58+Z1//vaa6+V8ePHy+jRo/29omnTpn3n8SUlJbJq1aru+2YPiBACgPA34MOwR40aJVlZWVJeXn7e80Xmi0o9bwCA8DfgAXTkyBH/HFB+fv5ATwoAEM6H4BoaGnrtzVRUVMiePXskIyPDvz311FMyd+5cfxTcgQMH5JFHHpHLL79cZs6c2d/zDgCIpADatWuX3Hbbbd33u87fLFy4UNatWyd79+6Vv/zlL1JTU+N/WXXGjBnyq1/9St23CAAQnkK2Gam5mS4KfWUeH0TjSS2b59KlqakpkOaJ9fX1opGenm5do1ndNB9eNM0dtfOnWX4jRoywromOth8z9P3vf180zJGLINaH//73v9Y1999/f2CNhzXrXkpKSiCNfdsVNdr3lc7OTuvHnz59mmakAIDQRAABAJwggAAAThBAAAAnCCAAgBMEEADACQIIAOAEAQQAcIIAAgA4QQABAJwggAAAThBAAAAnCCAAgBMh2w07KSnJqoP0kCH2WZqTkyMabW1t1jXmony2YmNjrWvi4+MDmY5hut3ayszMVK0TA929t0taWlogy+/gwYPWNeYaW0Gsq8bu3bsDWeaaDtrmemO2jh49Khqa7VazHDqV66uG5j3Cdj0yz8csO7phAwBCEgEEAHCCAAIAOEEAAQCcIIAAAE4QQAAAJwggAIATBBAAwAkCCADgBAEEAHCCAAIAOEEAAQCciJYQZZpC2jQYPXv2rPU0EhMTRUPTHLOwsNC65tSpU9Y1LS0tgS2H3Nxc65r29nbrGtOY1pamOa0RHW2/STQ1NVnXTJs2zbpm6tSp1jUTJ04UDc3y02yDFRUV1jX79++3rjlz5oxoaJqlJicnW9fU1NQE1sA0JiZmwLfBjo6OPjVyZQ8IAOAEAQQAcIIAAgA4QQABAJwggAAAThBAAAAnCCAAgBMEEADACQIIAOAEAQQAcIIAAgA4QQABAJwI2WakcXFxA96M9PTp0xJUM7+GhgYJgmkCaCsqKko1rb40G/y2zMxM6xrP86xrjh07JhoTJkywrlm6dGkgjUVNg15bbW1toqFpsKppwlleXh7IvGVnZ4tGa2trINt6tKIJrlZGRoZ1zcGDBwdkm2UPCADgBAEEAHCCAAIAOEEAAQCcIIAAAE4QQAAAJwggAIATBBAAwAkCCADgBAEEAHCCAAIAOEEAAQCcCNlmpO3t7VbNSBMTE62noWlgqm0caPNcei4DW52dnYE1Sk1NTbWuqaurs65JT0+3rnnkkUdEY8GCBdY1sbGxgTTH1KyvmnkzPvnkE+uaDRs2WNds27YtkKan9fX1oqFp1Nvc3BzI/CUrloO2YbFpDj0Q70PsAQEAnCCAAAChH0ClpaUyceJESUlJkZycHJkzZ47s27ev12NaWlpk2bJl/nVfzC7i3Llz5fjx4/093wCASAogc7zWhMvOnTvl/fff949Jz5gxQxobG7sfs3LlStm0aZN/PNg83lwY7O677x6IeQcADGJWZ9M3b97c635ZWZm/J7R7926ZMmWK1NbWyp///Gd59dVX5fbbb/cf8/LLL8tVV13lh9ZNN93Uv3MPAIjMc0AmcHpe4tUEkdkrmj59evdjxo4dK8XFxbJjx47zXvLWjIzqeQMAhD91AJlhditWrJCbb75ZrrnmGv93VVVV/rDPb1+7Pjc31//b+c4rmeG8XbeioiLtLAEAIiGAzLmgzz//XF5//fVLmoGSkhJ/T6rrdvjw4Uv6/wAAYfxF1OXLl8u7774r27dvl8LCwu7f5+XlSVtbm9TU1PTaCzKj4MzfzvcFJ9svOQEAImwPyPM8P3w2btwoH374oYwcObLX36+//nqJiYmRLVu2dP/ODNM+dOiQTJ48uf/mGgAQWXtA5rCbGeH2zjvv+N8F6jqvY87dJCQk+D/vv/9+WbVqlT8wYdiwYfLggw/64cMIOACAOoDWrVvn/5w6dWqv35uh1osWLfL//fvf/97ve2a+gGpGuM2cOVP++Mc/2kwGABABojxzXC2EmGHYZk9q+PDhVg08u4aE29Cee9I0Iw3qPJcJfVtDhw5VTUvTYHXcuHHWNatXr7auGT16tGgE1RRS02h2//791jXmw6HG3//+d+sacxQkiO2i5xffB7rxsOZ10jynWsX7l6ahrXZammakJ0+e9KdljoSdD73gAABOEEAAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMAJAggAMHiuiBoE073WptuypiOxuXieRktLi3VNbGxsIF1/x4wZY13zk5/8RDRuuOEG65qxY8da15iuurbMVXk1iouLrWt6XoCxr/76179a1+zduzewLtBBdW9vaGiwrrlQd+Xzqa6utq7RTis+Pj6QzvKpqamicebMGeua9PR0q8d3dHT0abtlDwgA4AQBBABwggACADhBAAEAnCCAAABOEEAAACcIIACAEwQQAMAJAggA4AQBBABwggACADhBAAEAnAjZZqSmOZ9Ngz5N405NU1FtE0BNE8577rnHuubKK68MpOGikZCQYF1z+vRp65r29vZAmr8azz33nHVNWVmZdU1nZ2cg66u2Galt80ntNmiaVtpqbm4ObFv3PM+6Jjra/m316NGjgaxD2m0jMTFxQF5X9oAAAE4QQAAAJwggAIATBBAAwAkCCADgBAEEAHCCAAIAOEEAAQCcIIAAAE4QQAAAJwggAIATBBAAwImQbUY6dOhQq2akycnJ1tOIiYkRDU2Dx1mzZlnX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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 11
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-25T07:17:06.489248Z",
     "start_time": "2025-08-25T07:17:06.484174Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch\n",
    "\n",
    "# 定义扩散参数\n",
    "T = 1000  # 总时间步\n",
    "betas = torch.linspace(0.0001, 0.02, T)\n",
    "alphas = 1 - betas\n",
    "alphas_bar = torch.cumprod(alphas, dim=0)\n",
    "\n",
    "# 对图像进行加噪\n",
    "def img_noise(img, t):\n",
    "    sqrt_alpha_bar_t = torch.sqrt(alphas_bar[t])\n",
    "    sqrt_one_minus_alpha_bar_t = torch.sqrt(1 - alphas_bar[t])\n",
    "    noise = torch.randn_like(img)\n",
    "    img_result = sqrt_alpha_bar_t * img + sqrt_one_minus_alpha_bar_t * noise\n",
    "\n",
    "    return img_result"
   ],
   "id": "39cb5936de12ad8f",
   "outputs": [],
   "execution_count": 12
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-25T07:17:07.897825Z",
     "start_time": "2025-08-25T07:17:07.892518Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 选择几个时间步进行可视化\n",
    "time_steps = [0, 50, 100, 300, 500, 700, 999]\n",
    "\n",
    "images_to_plot = []\n",
    "with torch.no_grad():\n",
    "    for t in time_steps:\n",
    "        t_tensor = torch.tensor([t])\n",
    "        img_result = img_noise(img, t_tensor)\n",
    "        # 转为 NumPy 用于显示\n",
    "        img_np = img_result.squeeze().cpu().numpy()\n",
    "        images_to_plot.append(img_np)"
   ],
   "id": "25ea72bc2e1b92f9",
   "outputs": [],
   "execution_count": 13
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-25T07:17:09.554403Z",
     "start_time": "2025-08-25T07:17:09.442601Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 可视化不同时间步的图像\n",
    "fig, axes = plt.subplots(1, len(images_to_plot), figsize=(15, 3))\n",
    "titles = [f\"t={t}\" for t in time_steps]\n",
    "\n",
    "for ax, img_plot, title in zip(axes, images_to_plot, titles):\n",
    "    ax.imshow(img_plot, cmap='gray')\n",
    "    ax.set_title(title)\n",
    "    ax.axis(\"off\")\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ],
   "id": "c6b7e80e3940095d",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 1500x300 with 7 Axes>"
      ],
      "image/png": "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166do3v27BFb/fr1zfNM48aNxZaammqaE9PT08XWtm1b01jTztP9+/eb1gP9+/cX20cffWRaXx06dEhsHTp0cDQhISGmx42PjzfN0Z9//rlpHrrpppscqyVLlogtOTnZdP5v27ZNbCkpKaZzQ1uD9O7d29GcPHlSbGvXrjWt+T744AOxXXPNNWJbvHix2PLz88V2xx13iG3BggVie/HFF8W2cOFCsU2bNs00Rx0/ftzRaGNVuw5r8/TXX39tOhbaPGWVmJhoWmNrc+3NN98sthkzZoitb9++prmttnsobVxo923fffed6dqmXfe1+9Krr77atDbduXOnaY3VqFEj0/v9yiuviC0tLc3RaGtQbe1WXFwstqKiIrGNHj1abG+//bbjbe3btxfbokWLxPbpp5+KbeDAgWKLiIgwzV1/+ctfTHNXbfc7SUlJYlu+fLnpfkfbd6hTp45pf0T7PG38amtTbX+gXr16pj3F3rWsFbTno61dtMfV5j3tmq+188F3pAMAAAAAAAAAoGAjHQAAAAAAAAAABRvpAAAAAAAAAAAo2EgHAAAAAAAAAEDBRjoAAAAAAAAAAAo20gEAAAAAAAAAUPh4PB6Pcx4CAgLEFhwcLLbKykqxBQYGiq28vNz0mKGhoWIrKSlxNNrrqKioML03Pj4+ptcRERHheNstt9witqCgILElJyeL7f777xfbX/7yF7GNGzfO0RQXF4vtjTfeENuTTz4pturqarH5+fmZjqH2PDVXXHGF2A4cOCC21q1bm16Ddv5mZmaKrWvXrmLLyspyNCdPnhRbx44dxbZx40axFRYWmsZ+XFyc2OrUqSO2oqIisbVt21ZsiYmJYmvcuLHYXn/9ddP41Y69q7S01PSeZmRkiO3QoUNi27Nnj9iaNGkitmXLljkWgwYNEltMTIzYcnJyxNaiRQvTtUs7D7/44guxXXzxxY5GO6cWLlwott69e4ttxowZYquqqhJb586dxTZ27FixzZw50zSeUlNTTe/bunXrxNajRw+xtW/f3tH4+/uLLS0tTWwffvih2CIjI03jsHnz5qb3W7Nr1y6xzZo1yzR+27RpI7bo6GjT3JWSkiK27du3OxptjXnJJZeI7dFHHxXbmDFjxObrK3/fyosvvii2zz//3LSG1D5PO2datmxpulZo6+v58+c7moSEBNN5c+rUKdPr2LBhg9jy8vLE9v777ztWt99+u+neIzc31zQPadch7doWFhZmuga5nn32WbHdeeedpnO1Xr16YisrKxPbDTfcILaVK1earpcrVqwwnadfffWVaSyeOXPGtDZ1hYeHOxbatdZ6bmj3Sa+88opjoa0/n3/+ebHl5+eLbfjw4aY1X8OGDcX2xz/+UWyXXnqpo9m5c6fYOnXq5Fg0aNBAbOnp6abrl7Y+CQkJMc1f2n2SNl8uWrRIbNdcc41pvnRFRUWJbdOmTWLbsmWL6Vqj7TsMHTpUbE888YRjsW/fPtN9gjYPacdQu+ZrewvaOkN7z2q719fmb+0Yaq9fW59p+2qrVq0yPc9mzZqZrpXadU1bR/Xr1880Dmtbuw0ZMsT0Og4ePGgao9q+YZcuXZza8B3pAAAAAAAAAAAo2EgHAAAAAAAAAEDBRjoAAAAAAAAAAAo20gEAAAAAAAAAULCRDgAAAAAAAACAgo10AAAAAAAAAAAU/s558vPzE1tVVZXYfHx8xFZZWelYBAYGiq20tFRs/v76y42LizN9zV69eomtR48eYouOjhbbyJEjTcdCe40ej0dsZWVlYsvNzRXbyy+/LLZLLrlEbCUlJY5mx44dYlu2bJnpnNLORY32vllVV1eLrbi42HTsQ0NDxbZt2zaxNWjQQGzHjh0zj999+/aJrUmTJmKbOHGi2BISEsRWXl5umqO053Lq1CmxNW3aVGyRkZFiW758udhGjRoltpYtW4otLy/P0Wjn/rRp00zvm/Ya69WrJ7aCggLH25KTk03jQju/N27caLpWaLTz9+jRo+rnLly4UGx33HGH2A4cOGC6drVo0UJsZ8+eNZ0XAwYMEFv37t3FFhsbK7aUlBTHQruma/OlKzEx0XSctPmkQ4cOpvNt1apVjrdp42Lx4sWmOfGmm24S29q1a03rjxkzZpjOmdrm2qVLl4pt8ODBYsvKyhLbnXfeKbaBAweaxsxrr70mtoqKCrFdd911YvvTn/4ktqCgILGNGTPGdG12HTlyRGynT58W26BBg8T28MMPi61Ro0Zi69atm/NLaNiwodhWrlxpWg99++23pq8XHh5uuuZr53dt55x2PzB37lzTPV3btm1Nc0rdunVNXy8/P19sYWFhpuv+kCFDxPbcc8+Zrt2u9PR003PVrkP9+vUzjeEtW7Y43jZr1izT+92qVSuxrVmzxnTOaPPQO++8I7bdu3c7mjNnzojt/fffF9vo0aPF5uvra9qv2LNnj9jat28vtubNm4ttzpw5YuvSpYtpHN54441iO3nypOk645o/f75pDGvr6Iceesi0ttHura1eeukl07nftWtX01pYOw+1eyFt76Rz586OZt68eWLbuXOn6blq97NXX321aa+uU6dOYtu7d69pj+DLL780fT1tPZSammq6NrsOHz5sGqdRUVGm+yTtHH7iiSfE9vnnnzu14TvSAQAAAAAAAABQsJEOAAAAAAAAAICCjXQAAAAAAAAAABRspAMAAAAAAAAAoGAjHQAAAAAAAAAABRvpAAAAAAAAAAAo/B0vqKioEFtQUJDYysvLTV/P4/GILSAgQGzt27dXH3fBggViq1+/vun5+PvLb3FZWZnY/Pz8xFZdXW16TwMDA8VWWVkptscee0xspaWlYpsxY4bYTpw4Ibba+sGDB03nW1VVlfOfYu/evWK79NJLxbZ//37TY2rnjPaeaU07n1zPPfec2BISEkznsHaedu3aVWy+vvLfGaampoqtUaNGpnP/iy++ENuuXbvEVlRUZHoNJ0+edDTaaywpKRFbcXGx6fVr79vgwYMdb9POU014eLjpfMrJyTF9vZiYGLFt2bJF/dxHHnnEdCxGjRplOr6dO3cWW/PmzcX27rvvii0iIsL0XPLy8kzndmZmptjWrFkjtpCQEEejjcVevXqZxsWnn35qeszCwkLH215//XWxXXXVVaZ56M9//rNp3rvkkkvEdsstt4ht6dKljkab91JSUsSWkZFhWmNmZWWZ1pAHDhwQW2hoqOlcW7t2rdjGjRtn+nra2uTIkSOOZt26dWJ7+OGHxbZs2TKxBQcHm45Tbesaq23btolt0qRJYktLSzPN0YcPHxbb0aNHTfPJHXfc4Whefvll03XozjvvNM3v2nU4KipKbGFhYWL78MMPTde9JUuWmNYS8+bNE9u9994rtvvvv9/RaHPKtddeazoWf/vb38R2++23i23fvn2Ot2nzjXa/M2HCBLHVqVNHbDfffLPpfl07n9LT0x3NwIEDxXb11Veb5uno6GixLV682HT9iouLM12HtOu+Ng9p14vWrVubxmjLli0dTZ8+fcT21ltveX2Noq2V+/Xr53ibdi/UpUsX0xysjUPtGA4ZMsS0x1fbnmKLFi3Elp2dbZr3tfdGu86eOnXKNA/Fxsaa1llTpkwxnYfPPPOM2AYNGiS2oUOHOhrtvNFev3YvqK2VmjRpIrbu3bs7PwffkQ4AAAAAAAAAgIKNdAAAAAAAAAAAFGykAwAAAAAAAACgYCMdAAAAAAAAAAAFG+kAAAAAAAAAACjYSAcAAAAAAAAAQMFGOgAAAAAAAAAACn/nPAUGBort7NmzYqusrBSbr6+vqWmqqqrElpWVpX5ufn6+2Bo0aGB6jVrT+Pn5iW3z5s1iy8vLE9uwYcNM79snn3xiOi8qKirMx1f7XOvneTweU/Px8XG8rVmzZmJbvXq12HJycsQWHR0tti5dupjGb3FxsdgyMzMdzeWXX+5YFBYWiq2kpERsSUlJYjtw4IDYysvLxVZaWiq2oqIi0/v9xBNPiK1hw4amcd++fXtHo50bp0+fNs1fHTt2FNvhw4fFtn79esfbtm7dKrb4+HhT27Fjh9iCg4PF1rx5c7GlpaWJrXHjxo51btMeNywsTGzZ2dliq1evnthWrFghtvT0dNOYSUxMNB2nLVu2mN6XsWPHiu3DDz90NNo8pF0vWrduLbYBAwaIrUmTJmI7ceKE420XX3yx2MLDw8U2d+5csQ0dOlRsMTExYtuwYYNpzaa9n7WtQbp37y62+fPne33OaNmypdjef/990/UiMjLSNH47dOggturqarG99957puuPq2/fvmJbtGiR2Pbt2ye2O++8U2wLFy4U27Jly8T20EMPOVbaOmPJkiWm46idN1FRUaa1mza3ac2VkZFhmm+1+4jk5GTTWlFr06dPF1uPHj3EdvLkSbG1adNGbEePHhVbQUGB2B5//HGx/e53v3M0a9euFVu3bt3EdvPNN4vt7rvvFtu9994rttjYWMfbtPVJWVmZ2ObNm2e6Dm3bts20rrHer7u6du0qtnfeeUdsTz75pOlratda7f5qzJgxYvvb3/5mmtu0deSkSZNMc5C2B1KbVq1aiS0oKMg0t2mvv2nTpmJbtWqV423aua/R5q/JkyeL7YUXXjDdI2p7VQ888ICj0caiv7+/6Rju2rXLdN9ivVZqe0BHjhwR2+7du8XWqFEjsbVt29Y07y1dutTRaHtL2lr5o48+Ms1Rx44dM127zwffkQ4AAAAAAAAAgIKNdAAAAAAAAAAAFGykAwAAAAAAAACgYCMdAAAAAAAAAAAFG+kAAAAAAAAAACjYSAcAAAAAAAAAQOHvnKfy8nKx+fj4iM3j8YgtICDA9PW0z9Pk5uaq/cknnxTbkCFDxLZlyxaxvfjii6b3bceOHWIbOXKk2CoqKsTWsmVLsd16662m56mpqqoSm7//eZ96/9bnas9Vez6BgYFiKysrc7ytsrLS9HljxowRW3p6utiqq6vFlpaWJrb69euLrU2bNo5mzZo1YmvevLnp+dx///1iy8zMFNuZM2fE9uyzz5qOU/fu3cVWVFQkti5dupjOUW1sa6/dlZCQILauXbua5qH8/HyxlZaWim3FihWOt0VGRootKytLbAcPHhRbTk6O2Lp162a65p06dUpsJSUljmbjxo1i69+/v9iWLl0qtuuvv15shw8fFluzZs3Etnz5ctM1ODo6WmybN282zVEDBw40PWbv3r0djXbua8dfe9wPPvhAbLGxsaa5zSooKMg01/To0UNs9erVM82zTZs2FVtycrLYPv74Y0fTqVMnsa1fv15sjz32mNhmzZplWpt88803Ymvbtq3YCgoKTOeotoY+evSo2FJTU8U2ZcoU01zqCg0NFdtf//pXsf3hD38Q25dffim2xMREsV188cXOL0E7x1NSUsR2ww03iO3pp582zUPac9m7d6/Y8vLyHI12Pl577bVi2717t9jCwsJM51VcXJzYwsPDxVa3bl3TWkkbU9r7pr2+Bg0aiO3zzz93NElJSWKbOXOm6XqqXTO1823OnDlimzp1qmOhrSW08bRp0ybTXHvnnXea1kPt27cXW69evRyN9lx///vfi2369Olii4+PF9vo0aPFdvz4cdM+x6RJk8T23nvvmcZadna26b5Uu37Vtv7Wzv1jx46JLSQkRGzt2rUT25/+9CexXXHFFY63aeeM9p6OGjXKNAdHRESY7pG1uXv8+PFiq61rc3THjh1N629tzaudTxptrtHuL95++23TfoV2rmmv77XXXnM02j2rdo+h7WNeeumlpvvgkydPOj8H35EOAAAAAAAAAICCjXQAAAAAAAAAABRspAMAAAAAAAAAoGAjHQAAAAAAAAAABRvpAAAAAAAAAAAo2EgHAAAAAAAAAEDh75wnj8cjNl9fX1OrrKwUW0BAgNiqq6tNrTafffaZ2BYtWiS2M2fOiK179+5iu+6668T20ksvia24uFhsgYGBYtu7d6/Y7rrrLtOx146hv798elVUVDgaPz8/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vlxsCQkJYsvOzhZbVFSU2J577jlHExYWJrb77rtPbKtWrRLbwIEDxZaRkSG2yMhIx9s2bdpkWgtOmTJFbNOnTzfNiYGBgWIbOnSo2Pbv3+9orOuB8vJyse3evVtse/fuFdvo0aPFdujQIbGNGzdObDt27DDNCb169TKNw5/js88+E1ujRo1Mc412DLU5Y/369c4v4YsvvhBbgwYNxNamTRuxnTlzRmyLFy82je+1a9eKLTY21tFoz1U7d7S1VIsWLUxjqmXLlmL785//LLYHHnhAbFu2bDGtzV988UXTtVSb27X1dW3v25w5c0zXIW298MYbb4itW7dujrdp14x9+/aJ7ejRo6bXFxISIrYNGzaY1p9//OMfHc2HH34otm+//dZ07m/evNn0XPfs2WOahxs2bCi2r776ynQe5uTkmMZFly5dzPezderUMY3h9u3bm+4VtGu7dm9ipc3Pr776qti2bt1qWmOdOHFCbB06dBBbVlaW2AoLCx2Ndl/es2dP0/3syy+/bLr/0NaRjz76qNhmzZoltuTkZNO9vHYMNY0bNzbd69Q2ZrS9w6efftp03lx00UXmdU1t+I50AAAAAAAAAAAUbKQDAAAAAAAAAKBgIx0AAAAAAAAAAAUb6QAAAAAAAAAAKNhIBwAAAAAAAABAwUY6AAAAAAAAAAAKf+c8VVVVic3j8YjN11feq/fx8TE9ZmBgoNjOnj0rtpCQEEdTWloqtoCAALE1bNhQbGPHjhXb3XffLbbY2FjT+1ZZWWk6Fps2bRLbc889J7avv/7adAy19/Pn0M5TPz8/0/MpKytzvK2kpERshw8fFltUVJTYEhISxHbkyBGx7d27V2wNGjQwnfeu3NxcsWVmZoqtdevWYpswYYLYevbsKba2bduaxlNKSorY8vPzxbZlyxbTPPP888+L7fTp02LbvHmzo7n66qvFlp6eLrY6deqYXr92nq5Zs8bxtkaNGomtqKjINF92795dbBkZGWKLi4sT29GjR03zkysxMVFsaWlpYrviiivEtmfPHrENHz5cbF27dhXbtm3bxNa7d2+x5eXlma752ty2bt060/utvXZXUlKS2L755huxRUdHm67B2rEvLCx0vE07Z+bNmye2119/XWwjRowQW9++fU3vpzaetHPbdfHFF4stJydHbCNHjhRbfHy8aY7eunWr2IqLi01fb+LEiWK76aabTHNbeXm52C699FKxffnll471+qSt27Ozs8W2f/9+03ypzd+/1NpUW5tr41u7tp06dUpsPXr0ML1v2vvtuuWWW8R26NAh09fUaK9DG/8PPvig2FauXGlaD0VGRprWJ0uWLDE95rFjxxxNmzZtxNaqVSuxxcTEmNZu2vzWuXNnx9u0ezatafc72ppWu5/R7llatGghtq+++srR+PvLWzSXX3652Dp27Ci2tWvXmtZS//M//2M6hxs3biy2e++9V2yLFi0y3bNp93pz5swR25VXXulotHlYu/eeOXOm2OrVqye2jRs3muYFq2uvvVZsWVlZpmtp8+bNTWNNO0eDg4NNY62282bBggViu+GGG8Q2cOBA016ONva1c1+7F/j2229N47CgoEBsTz/9tNimTp1q2jup7bzR7s20/YrXXntNbKmpqWJbuHCh2Lp06eLUhu9IBwAAAAAAAABAwUY6AAAAAAAAAAAKNtIBAAAAAAAAAFCwkQ4AAAAAAAAAgIKNdAAAAAAAAAAAFGykAwAAAAAAAACg8HfOk8fjMbXAwECxVVVVmR6zoqJCbH5+fqbHdCUmJootKSlJbH/961/F1qpVK9Pz8fW1/R3H1q1bxfb3v/9dbAsWLDAdJ+39DggIEFtlZaVjVdtxlJSVlZmeq7//eQ+T87Z9+3axderUSWwFBQWmsRYSEiK2EydOiC06Olpsp0+fdjQNGzYUW8uWLcX2zDPPiC01NdV0Xpw9e1ZskZGRYvvss8/EtmLFCtMctXfvXrENHDhQbNXV1WKLjY11NHv27BFbaWmp2Bo3bmwa+ykpKWI7ePCg423a+N28ebPYioqKxPbNN9+IrX379mLLzc0VW/fu3cW2ZMkSR6PNmdr7HRoaKrYbbrhBbIWFhWJLS0szzTXz5883zSfa9TcrK0tsbdq0EduBAwdMY8118uRJ07ynrQe0sZafny+2kpISx9u0a8mECRNMYy04OFhszz33nOn9HDFihNj69evnaFauXCm2cePGma4lmzZtEts111xjet/uu+8+0zk8a9YssdWvX19s7dq1E9tXX31lGjPaNda1bt0601xz5ZVXmsbMvn37TOf3zxETE2NaL2hrsNatW5uuz9qcedFFF4lt+fLljvUapc1TDzzwgOnavnbtWrF169ZNbL169RLbq6++KraIiAjTfNOiRQux+fj4mOaTyy67zNFMnjxZbFOnThVbZmam2BISEsT20EMPiS0jI8PxNm2+2bFjh9gGDBggtiNHjpjurU+dOmU6vtoc5briiitMa1dtT0Ibo1FRUWL7n//5H7E98sgjYlu9erXYFi9eLLZhw4aZ7sm1e2RtL0M79rWta7XXoR1/bU7UjuGZM2ccb9OuF3PmzBHb8OHDTevIOnXqmK6V2v1qTk6O2Gr7mr///e9N15m6deuK7fjx42K78cYbTedTcnKy6R5Cu0fU1tiPPvqoab4oqeW+RLsfWLNmjdiuuuoqsT355JOmc3Ho0KHOz8F3pAMAAAAAAAAAoGAjHQAAAAAAAAAABRvpAAAAAAAAAAAo2EgHAAAAAAAAAEDBRjoAAAAAAAAAAAo20gEAAAAAAAAAULCRDgAAAAAAAACAwt85T35+fmIrLy8XW2Vlpan5+PiIzddX3v+vX7++2F555RVH06lTJ7G1aNFCbB6PR2wVFRWm17Fu3Tqxvfzyy2JbtmyZ6ThZj73WtGMYEBCgfs0zZ86YPre6ulpsgYGBXv88q0GDBoktPDxcbPn5+abzKS8vT2x9+/YVW1BQkNg6duwotto+Nz4+Xmzfffed2Lp16ya2ffv2ia2wsFBszzzzjNg2bNggtlGjRpnGfZ06dcT26aefiq1fv35ii4yMdDSHDh0SW1VVldi2bdtmeh2lpaVi8/c/78vOeWvXrp3Y4uLixHb69GmxxcTEmM7Rzp07m47v9ddf72i0MZObmyu29u3biy05OVlsmZmZYlu6dKnYduzYIbaGDRuK7cSJE6b5WTufVq9eLbakpCTT2sSVnZ0ttqioKNOcqL3+hQsXii0sLMzxtqKiIrH9/e9/F9vhw4fFds8994gtMTFRbCEhIWKbPHmy2B555BFHc/vtt4ttz549Yvvggw/E9tRTT4mtZcuWptf42muvmcaT9fqrzQmXXXaZ2NavX29eQ/Xq1UtsHTp0EFtsbKxpXa69Du2aN3bsWMeqS5cuYjty5IjYMjIyxJaamiq2s2fPmtZu2nyiXUtdH374odi6d+9uWp9p1+jLL7/cNPc/+OCDYps0aZLYFixYILb9+/ebxrA2NurWrSu24OBgR6PdJzZp0kRs06ZNM10XtWuidk9jdfDgQdM5k5aWZlq3fv7556a9Be19qe2eXLvf27lzp9hGjx5tWmd8+eWXYuvfv7/YvvrqK9N5qt1DaI+pzV/avZd2Dd6+fbujGTZsmNhatWplev0HDhwQ2+7du01rc21vQTNjxgyxDR482HRP07p1a9M9i7b/1aZNG9NjuiZMmCC29PR0sV1yySWmMay9jqefflps//Vf/2W6L9X2gLT7JO3ape239ejRQ2yrVq1yNNo6Uzv3IyIiTPNJdHS0aY15PviOdAAAAAAAAAAAFGykAwAAAAAAAACgYCMdAAAAAAAAAAAFG+kAAAAAAAAAACjYSAcAAAAAAAAAQMFGOgAAAAAAAAAACn/nPHk8HvlB/OWH8fWV9+r9/PzE1r17d7HdeeedYuvSpYvYEhISHKvy8nLT66iqqhLbyy+/LLZnnnlGbMXFxabn4uPjYzq+2udpr09T2+cFBQWZPjcwMFBsZWVlpvetsrLS8baQkBCxLVmyRGyTJ08W24cffii2IUOGiG3o0KFiS0lJEVtRUZGjadSokdg6deoktuzsbLFt375dbMuWLRPboUOHxBYVFSW22NhYsR05ckRsffv2NY2nxMREsRUUFJjGr6tOnTqm11ivXj2xpaWlmc6NJk2aON42d+5csfXo0UNsubm5YgsICBBb165dxXbFFVeYjr02Rl2rVq0yPe6pU6fENn36dNOcqF2DtK9Xv359sY0aNUps3377renczs/PN401bfzWNkdnZmaKbfPmzaavGR0dbVp/We3bt09sAwYMENvSpUtNx7Bz585iu/7668X2yCOPmM6L2sb+0aNHTetIbW2iXbutc5Q2DkeMGCG2WbNmmdbQ9913n9juuece8zmakZHhWGjju3Xr1qb1/OnTp51fgjafaueUtnaJiIgQ2/Hjx8X24osvim3gwIFia9q0qaNJSkoS27Bhw8S2detWsZWUlIht7dq1YtuwYYPYwsPDTeeG9vq1c1G7tmvr3dLSUtN6oLa56OOPPxZbcnKy2OLi4sR27bXXiu3NN990vE17T7VjqF27tTXINddcI7YJEyaI7YsvvhDbXXfd5Wi0c0qbM86ePWuaFzp27Gg698PCwsQ2bdo0sd14441imz17ttgOHz4stuDgYNO19LHHHnM02uvQns/o0aPF1r9/f7Ht379fbN26dXO8bezYsab1kHb/qN2XaK+vurpabI8++qjY5s+f72gOHDggtk2bNoktNTXVtOfUtm1b0zpau7eOjIwU27Fj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FNuuXbvElpOT43jbvHnzTPOlNmYaN24stscee8w0t3Xq1Els77zzjqMZP3686fju37/fdO3+/PPPxXb99debrpUFBQWmcy0lJcV0/V24cKHY7rzzTtP4de3evdu0pi0qKhLbgQMHxNanTx+xfffdd84v4brrrjMdq6VLl4otISHBtG7Vxs27775rvp9ZvXq12A4ePCi2KVOmiK2iokJsY8eOFdsnn3xiOse11zh58mSxvfjii6b1kHbdi4iIMF3zXUOGDDG9fu0eIysry3QvqK17rLT35q233hJbZGSk2GJjY03PJSkpyXR9XrBggfq4AwYMMK1dT548abpP1K4nbdq0Edu3334rtttvv920runRo4fYZsyYIbYnnnjCtD5Zs2aNo/n666/FVlhYKLb+/fubxrD2fLS1q9U333xjukfs3bu32PLz88X23//932L74osvxLZy5UqxtW3b1tH069dPbI8++qjYkpOTTV8zPT1dbA8//LDY5syZI7ZNmzaZ1p+HDx823SNqY1u7Z01W3rParonaHH3mzBnTdWbw4MGmee988B3pAAAAAAAAAAAo2EgHAAAAAAAAAEDBRjoAAAAAAAAAAAo20gEAAAAAAAAAULCRDgAAAAAAAACAgo10AAAAAAAAAAAUPh6Px6N9AAAAAAAAAAAAv2V8RzoAAAAAAAAAAAo20gEAAAAAAAAAULCRDgAAAAAAAACAgo10AAAAAAAAAAAUbKQDAAAAAAAAAKBgIx0AAAAAAAAAAAUb6QAAAAAAAAAAKNhIBwAAAAAAAABAwUY6AAAAAAAAAACO7P8DcjJGxPOz81YAAAAASUVORK5CYII="
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 14
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 模型训练的过程",
   "id": "4e8cbd81452d640"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-25T06:40:26.692914Z",
     "start_time": "2025-08-25T06:40:26.640569Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch\n",
    "from torch.utils.data import DataLoader\n",
    "from torchvision import datasets, transforms\n",
    "from torch.optim import AdamW\n",
    "import numpy as np\n",
    "import os\n",
    "from PIL import Image\n",
    "\n",
    "# 训练数据\n",
    "dataset = datasets.MNIST(root='./data/', train=True, download=True, transform=transforms.ToTensor())\n",
    "subset_indices = list(range(10000))\n",
    "dataloader = DataLoader(dataset, batch_size=64, sampler=torch.utils.data.SubsetRandomSampler(subset_indices))\n",
    "\n",
    "# 训练参数\n",
    "T = 1000\n",
    "betas = torch.linspace(0.0001, 0.02, T)\n",
    "alphas = 1 - betas\n",
    "alphas_bar = torch.cumprod(alphas, dim=0)\n",
    "sqrt_alphas_bar = torch.sqrt(alphas_bar)\n",
    "sqrt_one_minus_alphas_bar = torch.sqrt(1 - alphas_bar)"
   ],
   "id": "95717840e03025f7",
   "outputs": [],
   "execution_count": 24
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-24T14:31:53.915258Z",
     "start_time": "2025-08-24T14:31:53.906683Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "\n",
    "# 两次卷积操作，卷积核为3，填充为1，使得输入和输出的尺寸一致\n",
    "class DoubleConv(nn.Module):\n",
    "    def __init__(self, in_ch, out_ch):\n",
    "        super(DoubleConv, self).__init__()\n",
    "        self.conv = nn.Sequential(\n",
    "            nn.Conv2d(in_ch, out_ch, 3, padding=1),\n",
    "            nn.BatchNorm2d(out_ch),\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.Conv2d(out_ch, out_ch, 3, padding=1),\n",
    "            nn.BatchNorm2d(out_ch),\n",
    "            nn.ReLU(inplace=True)\n",
    "        )\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.conv(x)\n",
    "\n",
    "# 下采样，图片缩小一半\n",
    "class Down(nn.Module):\n",
    "    def __init__(self, in_ch, out_ch):\n",
    "        super(Down, self).__init__()\n",
    "        self.mpconv = nn.Sequential(\n",
    "            nn.MaxPool2d(2),\n",
    "            DoubleConv(in_ch, out_ch)\n",
    "        )\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.mpconv(x)\n",
    "\n",
    "# 大都督周瑜（我的微信: it_zhouyu）\n",
    "\n",
    "# 上采样，图片放大两倍\n",
    "class Up(nn.Module):\n",
    "    def __init__(self, in_ch, out_ch):\n",
    "        super(Up, self).__init__()\n",
    "        self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)\n",
    "        self.conv = DoubleConv(in_ch, out_ch)\n",
    "\n",
    "    def forward(self, x1, x2):\n",
    "        x1 = self.up(x1)\n",
    "        # 裁剪并拼接跳跃连接\n",
    "        diffY = x2.size()[2] - x1.size()[2]\n",
    "        diffX = x2.size()[3] - x1.size()[3]\n",
    "        pad_left = diffX // 2\n",
    "        pad_right = diffX - pad_left\n",
    "        pad_top = diffY // 2\n",
    "        pad_bottom = diffY - pad_top\n",
    "        x1 = nn.functional.pad(x1, [pad_left, pad_right, pad_top, pad_bottom])\n",
    "        x = torch.cat([x2, x1], dim=1)\n",
    "\n",
    "        return self.conv(x)\n",
    "\n",
    "class OutConv(nn.Module):\n",
    "    def __init__(self, in_ch, out_ch):\n",
    "        super(OutConv, self).__init__()\n",
    "        # 卷积核大小为1，使得输出和输入尺寸一致，但还是变换了图片通道数\n",
    "        # out_ch=n_classes，n_classes=1，所以就是把之前的图片通道数变为1\n",
    "        # 最终整个UNet输入一张图片，输出也是一张图片\n",
    "        self.conv = nn.Conv2d(in_ch, out_ch, 1)\n",
    "\n",
    "    def forward(self, x):\n",
    "        # sigmoid是把像素值变为0-1之间\n",
    "        # return torch.sigmoid(self.conv(x))\n",
    "        return self.conv(x)\n",
    "\n",
    "class ZhouyuUNet(nn.Module):\n",
    "    def __init__(self, n_channels=1, n_classes=1, T=1000, time_emb_dim=64):\n",
    "        super(ZhouyuUNet, self).__init__()\n",
    "\n",
    "        self.time_emb = nn.Embedding(T, time_emb_dim)\n",
    "        self.time_proj = nn.Linear(time_emb_dim, 512)\n",
    "\n",
    "        self.inc = DoubleConv(n_channels, 64)\n",
    "        self.down1 = Down(64, 128)\n",
    "        self.down2 = Down(128, 256)\n",
    "        self.down3 = Down(256, 512)\n",
    "        self.down4 = Down(512, 512)\n",
    "        self.up1 = Up(512 + 512, 256)   # 通道数：512 (来自下采样) + 512 (上采样输入)\n",
    "        self.up2 = Up(256 + 256, 128)\n",
    "        self.up3 = Up(128 + 128, 64)\n",
    "        self.up4 = Up(64 + 64, 64)\n",
    "        self.outc = OutConv(64, n_classes)\n",
    "\n",
    "    def forward(self, x, t):\n",
    "        # 时间嵌入\n",
    "        time_emb = self.time_emb(t)\n",
    "        time_emb = self.time_proj(time_emb)\n",
    "        time_emb = time_emb.view(-1, 512, 1, 1)\n",
    "\n",
    "        x1 = self.inc(x)\n",
    "        x2 = self.down1(x1)\n",
    "        x3 = self.down2(x2)\n",
    "        x4 = self.down3(x3)\n",
    "        x5 = self.down4(x4)\n",
    "        x5 = x5 + time_emb # 加上时间嵌入\n",
    "        x = self.up1(x5, x4)\n",
    "        x = self.up2(x, x3)\n",
    "        x = self.up3(x, x2)\n",
    "        x = self.up4(x, x1)\n",
    "        x = self.outc(x)\n",
    "        return x"
   ],
   "id": "a88f30cf78287f09",
   "outputs": [],
   "execution_count": 17
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-24T14:32:25.796547Z",
     "start_time": "2025-08-24T14:31:57.959090Z"
    }
   },
   "cell_type": "code",
   "source": [
    "model = ZhouyuUNet(T=T, time_emb_dim=64)\n",
    "optimizer = AdamW(model.parameters(), lr=1e-4)\n",
    "criterion = nn.MSELoss()\n",
    "\n",
    "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
    "model.to(device)\n",
    "betas = betas.to(device)\n",
    "alphas = alphas.to(device)\n",
    "alphas_bar = alphas_bar.to(device)\n",
    "sqrt_alphas_bar = sqrt_alphas_bar.to(device)\n",
    "sqrt_one_minus_alphas_bar = sqrt_one_minus_alphas_bar.to(device)\n",
    "\n",
    "@torch.no_grad()\n",
    "def sample(model, num_samples=8):\n",
    "    model.eval()\n",
    "\n",
    "    # 随机生成num_samples个加了噪声的图片\n",
    "    x = torch.randn(num_samples, 1, 28, 28).to(device)\n",
    "    for t in reversed(range(T)):\n",
    "        t_tensor = torch.full((num_samples,), t, device=device, dtype=torch.long)\n",
    "\n",
    "        # 预测t时间步的噪声\n",
    "        noise_pred = model(x, t_tensor)\n",
    "\n",
    "        alpha = alphas[t]\n",
    "        alpha_bar = alphas_bar[t]\n",
    "        beta = betas[t]\n",
    "        if t > 0:\n",
    "            z = torch.randn_like(x)\n",
    "        else:\n",
    "            z = 0\n",
    "\n",
    "        # 核心是x-noise_pred得到t时间步对应的图像\n",
    "        x = (1 / torch.sqrt(alpha)) * (x - ((1 - alpha) / torch.sqrt(1 - alpha_bar)) * noise_pred) + torch.sqrt(beta) * z\n",
    "    return x.cpu()\n",
    "\n",
    "# 训练\n",
    "os.makedirs(\"samples\", exist_ok=True)\n",
    "\n",
    "epochs = 300\n",
    "print(\"开始训练...\")\n",
    "for epoch in range(epochs):\n",
    "    model.train()\n",
    "    total_loss = 0.0\n",
    "    for step, (images, _) in enumerate(dataloader):\n",
    "        batch_size = images.shape[0]\n",
    "        images = images.to(device)\n",
    "\n",
    "        # 生成一个噪声\n",
    "        noise = torch.randn_like(images)\n",
    "\n",
    "        # 随机一个时间步\n",
    "        t = torch.randint(0, T, (batch_size,), device=device)\n",
    "        sqrt_alpha_bar_t = sqrt_alphas_bar[t].view(-1, 1, 1, 1)\n",
    "        sqrt_one_minus_alpha_bar_t = sqrt_one_minus_alphas_bar[t].view(-1, 1, 1, 1)\n",
    "\n",
    "        # 添加噪声\n",
    "        xt = sqrt_alpha_bar_t * images + sqrt_one_minus_alpha_bar_t * noise\n",
    "\n",
    "        # 预测噪声\n",
    "        noise_pred = model(xt, t)\n",
    "\n",
    "        # 计算损失\n",
    "        loss = criterion(noise_pred, noise)\n",
    "\n",
    "        optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        # torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)  # 防止梯度爆炸\n",
    "        optimizer.step()\n",
    "\n",
    "        total_loss += loss.item()\n",
    "\n",
    "\n",
    "    avg_loss = total_loss / len(dataloader)\n",
    "    print(f\"Epoch [{epoch+1}/{epochs}], Loss: {avg_loss:.4f}\")\n",
    "\n",
    "    # 每 10 个 epoch 生成一次图片\n",
    "    if (epoch + 1) % 10 == 0:\n",
    "        gen_images = sample(model, num_samples=8)\n",
    "        gen_images = torch.clamp(gen_images, 0, 1) # 将预测结果的像素值截取到0-1，下面代码会乘以255\n",
    "        grid = torch.cat([img.squeeze() for img in gen_images], dim=1)\n",
    "        img = Image.fromarray((grid.numpy() * 255).astype(np.uint8))\n",
    "        img.save(f\"samples/epoch_{epoch+1:03d}.png\")\n",
    "        print(f\"存储图片到samples/epoch_{epoch+1:03d}.png\")"
   ],
   "id": "bd2ce4d33613788d",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "开始训练...\n",
      "Epoch [1/10], Loss: 0.9933\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[0;31mKeyboardInterrupt\u001B[0m                         Traceback (most recent call last)",
      "Cell \u001B[0;32mIn[18], line 80\u001B[0m\n\u001B[1;32m     78\u001B[0m \u001B[38;5;66;03m# 每 10 个 epoch 生成一次图片\u001B[39;00m\n\u001B[1;32m     79\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m (epoch \u001B[38;5;241m+\u001B[39m \u001B[38;5;241m1\u001B[39m) \u001B[38;5;241m%\u001B[39m \u001B[38;5;241m1\u001B[39m \u001B[38;5;241m==\u001B[39m \u001B[38;5;241m0\u001B[39m:\n\u001B[0;32m---> 80\u001B[0m     gen_images \u001B[38;5;241m=\u001B[39m \u001B[43msample\u001B[49m\u001B[43m(\u001B[49m\u001B[43mmodel\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mnum_samples\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;241;43m8\u001B[39;49m\u001B[43m)\u001B[49m\n\u001B[1;32m     81\u001B[0m     gen_images \u001B[38;5;241m=\u001B[39m torch\u001B[38;5;241m.\u001B[39mclamp(gen_images, \u001B[38;5;241m0\u001B[39m, \u001B[38;5;241m1\u001B[39m) \u001B[38;5;66;03m# 将预测结果的像素值截取到0-1，下面代码会乘以255\u001B[39;00m\n\u001B[1;32m     82\u001B[0m     grid \u001B[38;5;241m=\u001B[39m torch\u001B[38;5;241m.\u001B[39mcat([img\u001B[38;5;241m.\u001B[39msqueeze() \u001B[38;5;28;01mfor\u001B[39;00m img \u001B[38;5;129;01min\u001B[39;00m gen_images], dim\u001B[38;5;241m=\u001B[39m\u001B[38;5;241m1\u001B[39m)\n",
      "File \u001B[0;32m~/miniconda3/envs/mini-gpt/lib/python3.10/site-packages/torch/utils/_contextlib.py:116\u001B[0m, in \u001B[0;36mcontext_decorator.<locals>.decorate_context\u001B[0;34m(*args, **kwargs)\u001B[0m\n\u001B[1;32m    113\u001B[0m \u001B[38;5;129m@functools\u001B[39m\u001B[38;5;241m.\u001B[39mwraps(func)\n\u001B[1;32m    114\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[38;5;21mdecorate_context\u001B[39m(\u001B[38;5;241m*\u001B[39margs, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs):\n\u001B[1;32m    115\u001B[0m     \u001B[38;5;28;01mwith\u001B[39;00m ctx_factory():\n\u001B[0;32m--> 116\u001B[0m         \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[43mfunc\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43margs\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n",
      "Cell \u001B[0;32mIn[18], line 24\u001B[0m, in \u001B[0;36msample\u001B[0;34m(model, num_samples)\u001B[0m\n\u001B[1;32m     21\u001B[0m t_tensor \u001B[38;5;241m=\u001B[39m torch\u001B[38;5;241m.\u001B[39mfull((num_samples,), t, device\u001B[38;5;241m=\u001B[39mdevice, dtype\u001B[38;5;241m=\u001B[39mtorch\u001B[38;5;241m.\u001B[39mlong)\n\u001B[1;32m     23\u001B[0m \u001B[38;5;66;03m# 预测t时间步的噪声\u001B[39;00m\n\u001B[0;32m---> 24\u001B[0m noise_pred \u001B[38;5;241m=\u001B[39m \u001B[43mmodel\u001B[49m\u001B[43m(\u001B[49m\u001B[43mx\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mt_tensor\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m     26\u001B[0m alpha \u001B[38;5;241m=\u001B[39m alphas[t]\n\u001B[1;32m     27\u001B[0m alpha_bar \u001B[38;5;241m=\u001B[39m alphas_bar[t]\n",
      "File \u001B[0;32m~/miniconda3/envs/mini-gpt/lib/python3.10/site-packages/torch/nn/modules/module.py:1751\u001B[0m, in \u001B[0;36mModule._wrapped_call_impl\u001B[0;34m(self, *args, **kwargs)\u001B[0m\n\u001B[1;32m   1749\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_compiled_call_impl(\u001B[38;5;241m*\u001B[39margs, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)  \u001B[38;5;66;03m# type: ignore[misc]\u001B[39;00m\n\u001B[1;32m   1750\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[0;32m-> 1751\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_call_impl\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43margs\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n",
      "File \u001B[0;32m~/miniconda3/envs/mini-gpt/lib/python3.10/site-packages/torch/nn/modules/module.py:1762\u001B[0m, in \u001B[0;36mModule._call_impl\u001B[0;34m(self, *args, **kwargs)\u001B[0m\n\u001B[1;32m   1757\u001B[0m \u001B[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001B[39;00m\n\u001B[1;32m   1758\u001B[0m \u001B[38;5;66;03m# this function, and just call forward.\u001B[39;00m\n\u001B[1;32m   1759\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m (\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_backward_hooks \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_backward_pre_hooks \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_forward_hooks \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_forward_pre_hooks\n\u001B[1;32m   1760\u001B[0m         \u001B[38;5;129;01mor\u001B[39;00m _global_backward_pre_hooks \u001B[38;5;129;01mor\u001B[39;00m _global_backward_hooks\n\u001B[1;32m   1761\u001B[0m         \u001B[38;5;129;01mor\u001B[39;00m _global_forward_hooks \u001B[38;5;129;01mor\u001B[39;00m _global_forward_pre_hooks):\n\u001B[0;32m-> 1762\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[43mforward_call\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43margs\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m   1764\u001B[0m result \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[1;32m   1765\u001B[0m called_always_called_hooks \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mset\u001B[39m()\n",
      "Cell \u001B[0;32mIn[17], line 114\u001B[0m, in \u001B[0;36mZhouyuUNet.forward\u001B[0;34m(self, x, t)\u001B[0m\n\u001B[1;32m    112\u001B[0m x5 \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mdown4(x4)\n\u001B[1;32m    113\u001B[0m x5 \u001B[38;5;241m=\u001B[39m torch\u001B[38;5;241m.\u001B[39mcat([x5, time_emb], dim\u001B[38;5;241m=\u001B[39m\u001B[38;5;241m1\u001B[39m)\n\u001B[0;32m--> 114\u001B[0m x \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mup1\u001B[49m\u001B[43m(\u001B[49m\u001B[43mx5\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mx4\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m    115\u001B[0m x \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mup2(x, x3)\n\u001B[1;32m    116\u001B[0m x \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mup3(x, x2)\n",
      "File \u001B[0;32m~/miniconda3/envs/mini-gpt/lib/python3.10/site-packages/torch/nn/modules/module.py:1751\u001B[0m, in \u001B[0;36mModule._wrapped_call_impl\u001B[0;34m(self, *args, **kwargs)\u001B[0m\n\u001B[1;32m   1749\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_compiled_call_impl(\u001B[38;5;241m*\u001B[39margs, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)  \u001B[38;5;66;03m# type: ignore[misc]\u001B[39;00m\n\u001B[1;32m   1750\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[0;32m-> 1751\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_call_impl\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43margs\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n",
      "File \u001B[0;32m~/miniconda3/envs/mini-gpt/lib/python3.10/site-packages/torch/nn/modules/module.py:1762\u001B[0m, in \u001B[0;36mModule._call_impl\u001B[0;34m(self, *args, **kwargs)\u001B[0m\n\u001B[1;32m   1757\u001B[0m \u001B[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001B[39;00m\n\u001B[1;32m   1758\u001B[0m \u001B[38;5;66;03m# this function, and just call forward.\u001B[39;00m\n\u001B[1;32m   1759\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m (\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_backward_hooks \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_backward_pre_hooks \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_forward_hooks \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_forward_pre_hooks\n\u001B[1;32m   1760\u001B[0m         \u001B[38;5;129;01mor\u001B[39;00m _global_backward_pre_hooks \u001B[38;5;129;01mor\u001B[39;00m _global_backward_hooks\n\u001B[1;32m   1761\u001B[0m         \u001B[38;5;129;01mor\u001B[39;00m _global_forward_hooks \u001B[38;5;129;01mor\u001B[39;00m _global_forward_pre_hooks):\n\u001B[0;32m-> 1762\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[43mforward_call\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43margs\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m   1764\u001B[0m result \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m\n\u001B[1;32m   1765\u001B[0m called_always_called_hooks \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mset\u001B[39m()\n",
      "Cell \u001B[0;32mIn[17], line 67\u001B[0m, in \u001B[0;36mUp.forward\u001B[0;34m(self, x1, x2)\u001B[0m\n\u001B[1;32m     65\u001B[0m pad_top \u001B[38;5;241m=\u001B[39m diffY \u001B[38;5;241m/\u001B[39m\u001B[38;5;241m/\u001B[39m \u001B[38;5;241m2\u001B[39m\n\u001B[1;32m     66\u001B[0m pad_bottom \u001B[38;5;241m=\u001B[39m diffY \u001B[38;5;241m-\u001B[39m pad_top\n\u001B[0;32m---> 67\u001B[0m x1 \u001B[38;5;241m=\u001B[39m \u001B[43mnn\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mfunctional\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mpad\u001B[49m\u001B[43m(\u001B[49m\u001B[43mx1\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43m[\u001B[49m\u001B[43mpad_left\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mpad_right\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mpad_top\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mpad_bottom\u001B[49m\u001B[43m]\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m     68\u001B[0m x \u001B[38;5;241m=\u001B[39m torch\u001B[38;5;241m.\u001B[39mcat([x2, x1], dim\u001B[38;5;241m=\u001B[39m\u001B[38;5;241m1\u001B[39m)\n\u001B[1;32m     70\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mconv(x)\n",
      "File \u001B[0;32m~/miniconda3/envs/mini-gpt/lib/python3.10/site-packages/torch/nn/functional.py:5209\u001B[0m, in \u001B[0;36mpad\u001B[0;34m(input, pad, mode, value)\u001B[0m\n\u001B[1;32m   5202\u001B[0m         \u001B[38;5;28;01mif\u001B[39;00m mode \u001B[38;5;241m==\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mreplicate\u001B[39m\u001B[38;5;124m\"\u001B[39m:\n\u001B[1;32m   5203\u001B[0m             \u001B[38;5;66;03m# Use slow decomp whose backward will be in terms of index_put.\u001B[39;00m\n\u001B[1;32m   5204\u001B[0m             \u001B[38;5;66;03m# importlib is required because the import cannot be top level\u001B[39;00m\n\u001B[1;32m   5205\u001B[0m             \u001B[38;5;66;03m# (cycle) and cannot be nested (TS doesn't support)\u001B[39;00m\n\u001B[1;32m   5206\u001B[0m             \u001B[38;5;28;01mreturn\u001B[39;00m importlib\u001B[38;5;241m.\u001B[39mimport_module(\n\u001B[1;32m   5207\u001B[0m                 \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtorch._decomp.decompositions\u001B[39m\u001B[38;5;124m\"\u001B[39m\n\u001B[1;32m   5208\u001B[0m             )\u001B[38;5;241m.\u001B[39m_replication_pad(\u001B[38;5;28minput\u001B[39m, pad)\n\u001B[0;32m-> 5209\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[43mtorch\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_C\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_nn\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mpad\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;28;43minput\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mpad\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mmode\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mvalue\u001B[49m\u001B[43m)\u001B[49m\n",
      "\u001B[0;31mKeyboardInterrupt\u001B[0m: "
     ]
    }
   ],
   "execution_count": 18
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-24T14:19:31.208482Z",
     "start_time": "2025-08-24T14:19:15.680338Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "gen_images = sample(model, num_samples=8)\n",
    "gen_images = torch.clamp(gen_images, 0, 1) # 将预测结果的像素值截取到[0, 1]\n",
    "gen_images = gen_images * 255\n",
    "\n",
    "fig, axes = plt.subplots(2, 4, figsize=(12, 6))\n",
    "axes = axes.flatten()\n",
    "\n",
    "for i in range(8):\n",
    "    img = gen_images[i].squeeze().cpu().numpy()\n",
    "    axes[i].imshow(img, cmap='gray')\n",
    "    axes[i].axis(\"off\")\n",
    "\n",
    "plt.show()"
   ],
   "id": "d40f968cd5bb86c9",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 1200x600 with 8 Axes>"
      ],
      "image/png": "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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 10
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
